static inline size_t __glTexImage3D_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLint border) { size_t num_channels = __gl_format_channels(format); size_t bits_per_pixel; switch (type) { case GL_BITMAP: bits_per_pixel = 1; break; case GL_BYTE: case GL_UNSIGNED_BYTE: bits_per_pixel = 8 * num_channels; break; case GL_SHORT: case GL_UNSIGNED_SHORT: bits_per_pixel = 16 * num_channels; break; case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: bits_per_pixel = 32 * num_channels; break; case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: bits_per_pixel = 8; break; case GL_UNSIGNED_SHORT_4_4_4_4: case GL_UNSIGNED_SHORT_4_4_4_4_REV: case GL_UNSIGNED_SHORT_5_5_5_1: case GL_UNSIGNED_SHORT_1_5_5_5_REV: bits_per_pixel = 16; break; case GL_UNSIGNED_INT_8_8_8_8: case GL_UNSIGNED_INT_8_8_8_8_REV: case GL_UNSIGNED_INT_10_10_10_2: case GL_UNSIGNED_INT_2_10_10_10_REV: bits_per_pixel = 32; break; default: OS::DebugMessage("warning: %s: unexpected type GLenum 0x%04X\n", __FUNCTION__, type); bits_per_pixel = 0; break; } /* FIXME: consider glPixelStore settings */ size_t row_stride = (width*bits_per_pixel + 7)/8; size_t slice_stride = height*row_stride; return depth*slice_stride; }
/** * Dump the image of the currently bound read buffer. */ static inline void dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format) { GLint channels = __gl_format_channels(format); json.beginObject(); // Tell the GUI this is no ordinary object, but an image json.writeStringMember("__class__", "image"); json.writeNumberMember("__width__", width); json.writeNumberMember("__height__", height); json.writeNumberMember("__depth__", 1); // Hardcoded for now, but we could chose types more adequate to the // texture internal format json.writeStringMember("__type__", "uint8"); json.writeBoolMember("__normalized__", true); json.writeNumberMember("__channels__", channels); GLubyte *pixels = new GLubyte[width*height*channels]; resetPixelPackState(); glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, pixels); restorePixelPackState(); json.beginMember("__data__"); char *pngBuffer; int pngBufferSize; Image::writePixelsToBuffer(pixels, width, height, channels, false, &pngBuffer, &pngBufferSize); //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels) // <<", after = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize; json.writeBase64(pngBuffer, pngBufferSize); free(pngBuffer); json.endMember(); // __data__ delete [] pixels; json.endObject(); }
Image::Image * getDrawBufferImage(GLenum format) { GLint channels = __gl_format_channels(format); if (channels > 4) { return NULL; } GLint draw_framebuffer = 0; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_framebuffer); GLint draw_buffer = GL_NONE; GLint width, height; if (draw_framebuffer) { glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer); if (draw_buffer == GL_NONE) { return NULL; } if (!getFramebufferAttachmentSize(GL_DRAW_FRAMEBUFFER, draw_buffer, &width, &height)) { return NULL; } } else { glGetIntegerv(GL_DRAW_BUFFER, &draw_buffer); if (draw_buffer == GL_NONE) { return NULL; } if (!getDrawableBounds(&width, &height)) { return NULL; } } Image::Image *image = new Image::Image(width, height, channels, true); if (!image) { return NULL; } while (glGetError() != GL_NO_ERROR) {} GLint read_framebuffer = 0; glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &read_framebuffer); glBindFramebuffer(GL_READ_FRAMEBUFFER, draw_framebuffer); GLint read_buffer = 0; glGetIntegerv(GL_READ_BUFFER, &read_buffer); glReadBuffer(draw_buffer); resetPixelPackState(); glReadPixels(0, 0, width, height, format, GL_UNSIGNED_BYTE, image->pixels); restorePixelPackState(); glReadBuffer(read_buffer); glBindFramebuffer(GL_READ_FRAMEBUFFER, read_framebuffer); GLenum error = glGetError(); if (error != GL_NO_ERROR) { do { std::cerr << "warning: " << enumToString(error) << " while getting snapshot\n"; error = glGetError(); } while(error != GL_NO_ERROR); delete image; return NULL; } return image; }