static void get_texture_2d_image(image_info *info) { GLuint fbo = 0; GLint prev_fbo = 0; GLint texture; GLenum status; _glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture); if (!texture) return; _glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo); _glGenFramebuffers(1, &fbo); _glBindFramebuffer(GL_FRAMEBUFFER, fbo); _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); status = _glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) os::log("%s: error: %d\n", __func__, status); _glReadPixels(0, 0, info->width, info->height, info->format, info->type, info->pixels); /* Don't leak errors to the traced application. */ (void)_glGetError(); _glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo); _glDeleteFramebuffers(1, &fbo); }
void setContext(uintptr_t context_id) { ThreadState *ts = get_ts(); context_ptr_t ctx; context_map_mutex.lock(); assert(context_map.find(context_id) != context_map.end()); ctx = context_map[context_id]; context_map_mutex.unlock(); ts->current_context = ctx; if (!ctx->bound) { ctx->profile = glfeatures::getCurrentContextProfile(); ctx->extensions.getCurrentContextExtensions(ctx->profile); ctx->features.load(ctx->profile, ctx->extensions); ctx->bound = true; } if (!ctx->boundDrawable) { /* * The default viewport and scissor state is set when a context is * first made current, with values matching the bound drawable. Many * applications never thouch the default state ever again. * * Since we currently don't trace window sizes, and rely on viewport * calls to deduct, emit fake calls here so that viewport/scissor state * can be deducated. * * FIXME: don't call the real functions here -- just emit the fake * calls. */ GLint viewport[4] = {0, 0, 0, 0}; GLint scissor[4] = {0, 0, 0, 0}; _glGetIntegerv(GL_VIEWPORT, viewport); _glGetIntegerv(GL_SCISSOR_BOX, scissor); /* * On MacOSX the current context and surface are set independently, and * we might be called before both are set, so ignore empty boxes. */ if (viewport[2] && viewport[3] && scissor[2] && scissor[3]) { glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); ctx->boundDrawable = true; } } }
struct image_info * _EGLImageKHR_get_image_info(GLenum target, EGLImageKHR image) { GLuint tex; GLuint bound_tex; struct image_info *info; info = new image_info; memset(info, 0, sizeof *info); info->internalformat = GL_RGBA; info->format = GL_RGBA; info->type = GL_UNSIGNED_BYTE; _eglCreateImageKHR_get_image_size(image, info); _glGenTextures(1, &tex); _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&bound_tex); _glBindTexture(GL_TEXTURE_2D, tex); _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); info->size = _glTexImage2D_size(info->format, info->type, info->width, info->height); info->pixels = malloc(info->size); get_texture_2d_image(info); _glBindTexture(GL_TEXTURE_2D, bound_tex); _glDeleteBuffers(1, &tex); return info; }
void _glGetIntegerv_override(GLenum pname, GLint *params) { _glGetIntegerv(pname, params); if (params) { const Context *ctx; switch (pname) { case GL_NUM_EXTENSIONS: ctx = getContext(); if (ctx->profile.major >= 3) { const ExtensionsDesc *desc = getExtraExtensions(ctx); *params += desc->numStrings; } break; case GL_MAX_LABEL_LENGTH: /* We provide our default implementation of KHR_debug when the * driver does not. So return something sensible here. */ if (params[0] == 0) { params[0] = 256; } break; default: break; } } }
static void _eglCreateImageKHR_get_image_size(EGLImageKHR image, image_info *info) { GLuint fbo = 0; GLuint orig_fbo = 0; GLuint texture = 0; GLuint orig_texture; GLenum status; _glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&orig_fbo); _glGenFramebuffers(1, &fbo); _glBindFramebuffer(GL_FRAMEBUFFER, fbo); _glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *)&orig_texture); _glGenTextures(1, &texture); _glBindTexture(GL_TEXTURE_2D, texture); _glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); info->width = 0; info->height = 0; _glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); status = _glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status == GL_FRAMEBUFFER_COMPLETE) { if (detect_size(&info->width, &info->height) != 0) os::log("%s: can't detect image size\n", __func__); } else { os::log("%s: error: %x\n", __func__, status); } /* Don't leak errors to the traced application. */ (void)_glGetError(); _glBindTexture(GL_TEXTURE_2D, orig_texture); _glDeleteTextures(1, &texture); _glBindFramebuffer(GL_FRAMEBUFFER, orig_fbo); _glDeleteFramebuffers(1, &fbo); }
static inline size_t _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage) { unsigned bits_per_element; unsigned bits_per_pixel; _gl_format_size(format, type, bits_per_element, bits_per_pixel); GLint alignment = 4; GLint row_length = 0; GLint image_height = 0; GLint skip_rows = 0; GLint skip_pixels = 0; GLint skip_images = 0; _glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); if (has_unpack_subimage) { _glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); _glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &image_height); _glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); _glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); _glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &skip_images); } if (row_length <= 0) { row_length = width; } size_t row_stride = (row_length*bits_per_pixel + 7)/8; if ((bits_per_element == 1*8 || bits_per_element == 2*8 || bits_per_element == 4*8 || bits_per_element == 8*8) && (GLint)bits_per_element < alignment*8) { row_stride = _align(row_stride, alignment); } if (image_height <= 0) { image_height = height; } /* XXX: GL_UNPACK_IMAGE_HEIGHT and GL_UNPACK_SKIP_IMAGES should probably * not be considered for pixel rectangles. */ size_t image_stride = image_height*row_stride; size_t size = depth*image_stride; size += (skip_pixels*bits_per_pixel + 7)/8; size += skip_rows*row_stride; size += skip_images*image_stride; return size; }
void _glGetIntegerv_override(GLenum pname, GLint *params) { _glGetIntegerv(pname, params); if (params) { switch (pname) { case GL_NUM_EXTENSIONS: { const ExtensionsDesc *desc = getExtraExtensions(); *params += desc->numStrings; } break; default: break; } } }
const GLubyte * _glGetStringi_override(GLenum name, GLuint index) { switch (name) { case GL_EXTENSIONS: { const ExtensionsDesc *desc = getExtraExtensions(); GLint numExtensions = 0; _glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); if ((GLuint)numExtensions <= index && index < (GLuint)numExtensions + desc->numStrings) { return (const GLubyte *)desc->strings[index - (GLuint)numExtensions]; } } break; default: break; } return _glGetStringi(name, index); }
static int detect_size(int *width_ret, int *height_ret) { GLint max_tex_size; int width; int height; max_tex_size = 0; _glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); width = bisect_val(1, max_tex_size, is_valid_width); if (width < 0) return -1; height = bisect_val(1, max_tex_size, is_valid_height); if (height < 0) return -1; *width_ret = width; *height_ret = height; return 0; }
/** * Same as glGetIntegerv, but passing the result in the return value. */ static inline GLint _glGetInteger(GLenum pname) { GLint param = 0; _glGetIntegerv(pname, ¶m); return param; }
static inline size_t _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage) { unsigned num_channels = _gl_format_channels(format); unsigned bits_per_element; unsigned bits_per_pixel; switch (type) { case GL_BITMAP: bits_per_pixel = bits_per_element = 1; break; case GL_BYTE: case GL_UNSIGNED_BYTE: bits_per_element = 8; bits_per_pixel = bits_per_element * num_channels; break; case GL_SHORT: case GL_UNSIGNED_SHORT: case GL_HALF_FLOAT: bits_per_element = 16; bits_per_pixel = bits_per_element * num_channels; break; case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: bits_per_element = 32; bits_per_pixel = bits_per_element * num_channels; break; case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: bits_per_pixel = bits_per_element = 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: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: case GL_UNSIGNED_SHORT_8_8_MESA: case GL_UNSIGNED_SHORT_8_8_REV_MESA: bits_per_pixel = bits_per_element = 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: case GL_UNSIGNED_INT_24_8: case GL_UNSIGNED_INT_10F_11F_11F_REV: case GL_UNSIGNED_INT_5_9_9_9_REV: case GL_UNSIGNED_INT_S8_S8_8_8_NV: case GL_UNSIGNED_INT_8_8_S8_S8_REV_NV: bits_per_pixel = bits_per_element = 32; break; case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: bits_per_pixel = bits_per_element = 64; break; default: os::log("apitrace: warning: %s: unexpected type GLenum 0x%04X\n", __FUNCTION__, type); bits_per_pixel = bits_per_element = 0; break; } GLint alignment = 4; GLint row_length = 0; GLint image_height = 0; GLint skip_rows = 0; GLint skip_pixels = 0; GLint skip_images = 0; _glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); if (has_unpack_subimage) { _glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); _glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &image_height); _glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); _glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); _glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &skip_images); } if (row_length <= 0) { row_length = width; } size_t row_stride = (row_length*bits_per_pixel + 7)/8; if ((bits_per_element == 1*8 || bits_per_element == 2*8 || bits_per_element == 4*8 || bits_per_element == 8*8) && (GLint)bits_per_element < alignment*8) { row_stride = _align(row_stride, alignment); } if (image_height <= 0) { image_height = height; } /* XXX: GL_UNPACK_IMAGE_HEIGHT and GL_UNPACK_SKIP_IMAGES should probably * not be considered for pixel rectangles. */ size_t image_stride = image_height*row_stride; size_t size = depth*image_stride; size += (skip_pixels*bits_per_pixel + 7)/8; size += skip_rows*row_stride; size += skip_images*image_stride; return size; }
static inline GLuint _glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex) { GLvoid *temp = 0; GLint element_array_buffer = 0; if (!count) { return 0; } _glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &element_array_buffer); if (element_array_buffer) { // Read indices from index buffer object GLintptr offset = (GLintptr)indices; GLsizeiptr size = count*_gl_type_size(type); GLvoid *temp = malloc(size); if (!temp) { return 0; } memset(temp, 0, size); _glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, temp); indices = temp; } else { if (!indices) { return 0; } } GLuint maxindex = 0; GLsizei i; if (type == GL_UNSIGNED_BYTE) { const GLubyte *p = (const GLubyte *)indices; for (i = 0; i < count; ++i) { if (p[i] > maxindex) { maxindex = p[i]; } } } else if (type == GL_UNSIGNED_SHORT) { const GLushort *p = (const GLushort *)indices; for (i = 0; i < count; ++i) { if (p[i] > maxindex) { maxindex = p[i]; } } } else if (type == GL_UNSIGNED_INT) { const GLuint *p = (const GLuint *)indices; for (i = 0; i < count; ++i) { if (p[i] > maxindex) { maxindex = p[i]; } } } else { os::log("apitrace: warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type); } if (element_array_buffer) { free(temp); } maxindex += basevertex; return maxindex + 1; }
static inline size_t _gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage) { unsigned bits_per_pixel = _gl_format_size(format, type); GLint alignment = 4; GLint row_length = 0; GLint image_height = 0; GLint skip_rows = 0; GLint skip_pixels = 0; GLint skip_images = 0; _glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); if (has_unpack_subimage) { _glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); _glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &image_height); _glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); _glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); _glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &skip_images); } if (row_length <= 0) { row_length = width; } size_t row_stride = (row_length*bits_per_pixel + 7)/8; /* * The OpenGL specification states that the unpack alignment should be * ignored if the number of bits per element is not 1, 2, 4, or 8 times the * number of bits in a GL ubyte, but the matter of fact is that the number * of bits per element is always one of those. */ if (_is_pot(alignment)) { row_stride = _align(row_stride, alignment); } if (image_height <= 0) { image_height = height; } size_t image_stride = image_height*row_stride; /* * We can't just do * * size = depth*image_stride * * here as that could result in reading beyond the end of the buffer when * selecting sub-rectangles via GL_UNPACK_SKIP_*. */ size_t size = (width*bits_per_pixel + 7)/8; if (height > 1) { size += (height - 1)*row_stride; } if (depth > 1) { size += (depth - 1)*image_stride; } /* XXX: GL_UNPACK_IMAGE_HEIGHT and GL_UNPACK_SKIP_IMAGES should probably * not be considered for pixel rectangles. */ size += (skip_pixels*bits_per_pixel + 7)/8; size += skip_rows*row_stride; size += skip_images*image_stride; return size; }