From 7b09710392d35fb55b52031d447a542d99fc6b4b Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 19 Aug 2014 17:10:03 -0400 Subject: Modularize the libdimension codebase. --- libdimension/canvas/gl.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 libdimension/canvas/gl.c (limited to 'libdimension/canvas/gl.c') diff --git a/libdimension/canvas/gl.c b/libdimension/canvas/gl.c new file mode 100644 index 0000000..900f53c --- /dev/null +++ b/libdimension/canvas/gl.c @@ -0,0 +1,113 @@ +/************************************************************************* + * Copyright (C) 2009-2014 Tavian Barnes * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * . * + *************************************************************************/ + +/** + * @file + * OpenGL import/export. + */ + +#include "internal/rgba.h" +#include "dimension/canvas.h" +#include +#include +#include +#include + +// Optimize canvas for GL drawing +int +dmnsn_gl_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas) +{ + dmnsn_rgba8_optimize_canvas(pool, canvas); + return 0; +} + +// Write canvas to GL framebuffer. Returns 0 on success, nonzero on failure +int +dmnsn_gl_write_canvas(const dmnsn_canvas *canvas) +{ + size_t width = canvas->width; + size_t height = canvas->height; + + // Check if we can optimize this + dmnsn_rgba8_optimizer *rgba8 = (dmnsn_rgba8_optimizer *)dmnsn_canvas_find_optimizer(canvas, dmnsn_rgba8_optimizer_fn); + if (rgba8) { + glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, rgba8->data); + return glGetError() == GL_NO_ERROR ? 0 : 1; + } + + // We couldn't, so transform the canvas to RGB now + GLubyte *pixels = dmnsn_malloc(4*width*height*sizeof(GLubyte)); + + for (size_t y = 0; y < height; ++y) { + for (size_t x = 0; x < width; ++x) { + GLubyte *pixel = pixels + 4*(y*width + x); + + dmnsn_tcolor tcolor = dmnsn_canvas_get_pixel(canvas, x, y); + tcolor = dmnsn_tcolor_remove_filter(tcolor); + tcolor.c = dmnsn_color_to_sRGB(tcolor.c); + tcolor = dmnsn_tcolor_clamp(tcolor); + + pixel[0] = lround(tcolor.c.R*UINT8_MAX); + pixel[1] = lround(tcolor.c.G*UINT8_MAX); + pixel[2] = lround(tcolor.c.B*UINT8_MAX); + pixel[3] = lround(tcolor.T*UINT8_MAX); + } + } + + glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + dmnsn_free(pixels); + return glGetError() == GL_NO_ERROR ? 0 : 1; +} + +// Read a canvas from a GL framebuffer. Returns NULL on failure. +int +dmnsn_gl_read_canvas(dmnsn_canvas *canvas, size_t x0, size_t y0) +{ + size_t width = canvas->width; + size_t height = canvas->height; + + // Array of 16-bit ints in RGBA order + GLushort *pixels = dmnsn_malloc(4*width*height*sizeof(GLushort)); + glReadPixels(x0, y0, width, height, GL_RGBA, GL_UNSIGNED_SHORT, pixels); + if (glGetError() != GL_NO_ERROR) { + dmnsn_free(pixels); + return -1; + } + + for (size_t y = 0; y < height; ++y) { + for (size_t x = 0; x < width; ++x) { + GLushort *pixel = pixels + 4*(y*width + x); + + dmnsn_tcolor tcolor = dmnsn_new_tcolor5( + (double)pixel[0]/UINT16_MAX, + (double)pixel[1]/UINT16_MAX, + (double)pixel[2]/UINT16_MAX, + (double)pixel[3]/UINT16_MAX, + 0.0 + ); + tcolor.c = dmnsn_color_from_sRGB(tcolor.c); + dmnsn_canvas_set_pixel(canvas, x, y, tcolor); + } + } + + dmnsn_free(pixels); + return 0; +} -- cgit v1.2.3