void dumpTextures(JSONWriter &json, Context &context) { json.beginMember("textures"); json.beginObject(); GLint active_texture = GL_TEXTURE0; glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); GLint max_texture_coords = 0; glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords); GLint max_combined_texture_image_units = 0; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units); GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords); /* * At least the Android software GL implementation doesn't return the * proper value for this, but rather returns 0. The GL(ES) specification * mandates a minimum value of 2, so use this as a fall-back value. */ max_units = std::max(max_units, 2); for (GLint unit = 0; unit < max_units; ++unit) { GLenum texture = GL_TEXTURE0 + unit; glActiveTexture(texture); dumpTexture(json, context, GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D); dumpTexture(json, context, GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D); dumpTexture(json, context, GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D); dumpTexture(json, context, GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE); dumpTexture(json, context, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP); } glActiveTexture(active_texture); json.endObject(); json.endMember(); // textures }
/** * Dump the image of the currently bound read buffer. */ static inline void dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format, GLint internalFormat = GL_NONE) { GLint channels = _gl_format_channels(format); if (internalFormat == GL_NONE) { internalFormat = format; } Context context; 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); json.writeStringMember("__format__", enumToString(internalFormat)); // 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); GLenum type = GL_UNSIGNED_BYTE; #if DEPTH_AS_RGBA if (format == GL_DEPTH_COMPONENT) { type = GL_UNSIGNED_INT; channels = 4; } #endif GLubyte *pixels = new GLubyte[width*height*channels]; // TODO: reset imaging state too context.resetPixelPackState(); glReadPixels(0, 0, width, height, format, type, pixels); context.restorePixelPackState(); json.beginMember("__data__"); char *pngBuffer; int pngBufferSize; image::writePixelsToBuffer(pixels, width, height, channels, true, &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(); }
void dumpTextures(JSONWriter &json, ID3D11DeviceContext *pDevice) { json.beginMember("textures"); json.beginObject(); ID3D11ShaderResourceView *pShaderResourceViews[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT]; pDevice->VSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); dumpStageTextures(json, pDevice, "VS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); pDevice->HSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); dumpStageTextures(json, pDevice, "HS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); pDevice->DSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); dumpStageTextures(json, pDevice, "DS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); pDevice->GSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); dumpStageTextures(json, pDevice, "GS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); pDevice->PSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); dumpStageTextures(json, pDevice, "PS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews); json.endObject(); json.endMember(); // textures }
static inline void dumpTextures(JSONWriter &json) { json.beginMember("textures"); json.beginObject(); GLint active_texture = GL_TEXTURE0; glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); GLint max_texture_coords = 0; glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords); GLint max_combined_texture_image_units = 0; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_combined_texture_image_units); GLint max_units = std::max(max_combined_texture_image_units, max_texture_coords); for (GLint unit = 0; unit < max_units; ++unit) { GLenum texture = GL_TEXTURE0 + unit; glActiveTexture(texture); dumpTexture(json, GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D); dumpTexture(json, GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D); dumpTexture(json, GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D); dumpTexture(json, GL_TEXTURE_RECTANGLE, GL_TEXTURE_BINDING_RECTANGLE); dumpTexture(json, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP); } glActiveTexture(active_texture); json.endObject(); json.endMember(); // textures }
static void dumpShaders(JSONWriter &json, ID3D10Device *pDevice) { json.beginMember("shaders"); json.beginObject(); com_ptr<ID3D10VertexShader> pVertexShader; pDevice->VSGetShader(&pVertexShader); if (pVertexShader) { dumpShader<ID3D10DeviceChild>(json, "VS", pVertexShader); } com_ptr<ID3D10GeometryShader> pGeometryShader; pDevice->GSGetShader(&pGeometryShader); if (pGeometryShader) { dumpShader<ID3D10DeviceChild>(json, "GS", pGeometryShader); } com_ptr<ID3D10PixelShader> pPixelShader; pDevice->PSGetShader(&pPixelShader); if (pPixelShader) { dumpShader<ID3D10DeviceChild>(json, "PS", pPixelShader); } json.endObject(); json.endMember(); // shaders }
void dumpTextures(JSONWriter &json, IDirect3DDevice7 *pDevice) { json.beginMember("textures"); json.beginObject(); json.endObject(); json.endMember(); // textures }
void dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDevice) { json.beginMember("framebuffer"); json.beginObject(); ID3D11RenderTargetView *pRenderTargetViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; ID3D11DepthStencilView *pDepthStencilView; pDevice->OMGetRenderTargets(ARRAYSIZE(pRenderTargetViews), pRenderTargetViews, &pDepthStencilView); for (UINT i = 0; i < ARRAYSIZE(pRenderTargetViews); ++i) { if (!pRenderTargetViews[i]) { continue; } image::Image *image; DXGI_FORMAT dxgiFormat; image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i], &dxgiFormat); if (image) { char label[64]; _snprintf(label, sizeof label, "RENDER_TARGET_%u", i); JSONWriter::ImageDesc imgDesc; imgDesc.depth = 1; imgDesc.format = getDXGIFormatName(dxgiFormat); json.beginMember(label); json.writeImage(image, imgDesc); json.endMember(); // RENDER_TARGET_* delete image; } pRenderTargetViews[i]->Release(); } if (pDepthStencilView) { image::Image *image; DXGI_FORMAT dxgiFormat; image = getDepthStencilViewImage(pDevice, pDepthStencilView, &dxgiFormat); if (image) { JSONWriter::ImageDesc imgDesc; imgDesc.depth = 1; imgDesc.format = getDXGIFormatName(dxgiFormat); json.beginMember("DEPTH_STENCIL"); json.writeImage(image, imgDesc); json.endMember(); delete image; } pDepthStencilView->Release(); } json.endObject(); json.endMember(); // framebuffer }
static inline void dumpShaders(JSONWriter &json) { json.beginMember("shaders"); json.beginObject(); dumpCurrentProgram(json); dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB); dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB); json.endObject(); json.endMember(); //shaders }
static void dumpProgramUniformsStage(JSONWriter &json, GLint program, const char *stage) { if (program) { json.beginMember(stage); json.beginObject(); dumpProgramUniforms(json, program); json.endObject(); json.endMember(); } }
void dumpFramebuffer(JSONWriter &json, IDirect3DDevice9 *pDevice) { HRESULT hr; json.beginMember("framebuffer"); json.beginObject(); D3DCAPS9 Caps; pDevice->GetDeviceCaps(&Caps); for (UINT i = 0; i < Caps.NumSimultaneousRTs; ++i) { IDirect3DSurface9 *pRenderTarget = NULL; hr = pDevice->GetRenderTarget(i, &pRenderTarget); if (FAILED(hr)) { continue; } if (!pRenderTarget) { continue; } image::Image *image; image = getRenderTargetImage(pDevice, pRenderTarget); if (image) { char label[64]; _snprintf(label, sizeof label, "RENDER_TARGET_%u", i); json.beginMember(label); json.writeImage(image, "UNKNOWN"); json.endMember(); // RENDER_TARGET_* } pRenderTarget->Release(); } IDirect3DSurface9 *pDepthStencil = NULL; hr = pDevice->GetDepthStencilSurface(&pDepthStencil); if (SUCCEEDED(hr) && pDepthStencil) { image::Image *image; image = getSurfaceImage(pDevice, pDepthStencil); if (image) { json.beginMember("DEPTH_STENCIL"); json.writeImage(image, "UNKNOWN"); json.endMember(); // RENDER_TARGET_* } } json.endObject(); json.endMember(); // framebuffer }
static void dumpParameters(JSONWriter &json, ID3D11DeviceContext *pDeviceContext) { // TODO: dump description of current bound state json.beginMember("parameters"); json.beginObject(); dumpRasterizerState(json, pDeviceContext); dumpBlendState(json, pDeviceContext); dumpDepthStencilState(json, pDeviceContext); json.endObject(); json.endMember(); // parameters }
void dumpTextures(JSONWriter &json, IDirect3DDevice9 *pDevice) { HRESULT hr; json.beginMember("textures"); json.beginObject(); for (DWORD Stage = 0; Stage < 16; ++Stage) { com_ptr<IDirect3DBaseTexture9> pTexture; hr = pDevice->GetTexture(Stage, &pTexture); if (FAILED(hr)) { continue; } if (!pTexture) { continue; } D3DRESOURCETYPE Type = pTexture->GetType(); DWORD NumFaces = Type == D3DRTYPE_CUBETEXTURE ? 6 : 1; DWORD NumLevels = pTexture->GetLevelCount(); for (DWORD Face = 0; Face < NumFaces; ++Face) { for (DWORD Level = 0; Level < NumLevels; ++Level) { image::Image *image; image = getTextureImage(pDevice, pTexture, static_cast<D3DCUBEMAP_FACES>(Face), Level); if (image) { char label[128]; if (Type == D3DRTYPE_CUBETEXTURE) { _snprintf(label, sizeof label, "PS_RESOURCE_%lu_FACE_%lu_LEVEL_%lu", Stage, Face, Level); } else { _snprintf(label, sizeof label, "PS_RESOURCE_%lu_LEVEL_%lu", Stage, Level); } json.beginMember(label); json.writeImage(image); json.endMember(); // PS_RESOURCE_* } } } } json.endObject(); json.endMember(); // textures }
void dumpFramebuffer(JSONWriter &json, ID3D10Device *pDevice) { json.beginMember("framebuffer"); json.beginObject(); ID3D10RenderTargetView *pRenderTargetViews[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT]; ID3D10DepthStencilView *pDepthStencilView; pDevice->OMGetRenderTargets(ARRAYSIZE(pRenderTargetViews), pRenderTargetViews, &pDepthStencilView); for (UINT i = 0; i < ARRAYSIZE(pRenderTargetViews); ++i) { if (!pRenderTargetViews[i]) { continue; } image::Image *image; image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i]); if (image) { char label[64]; _snprintf(label, sizeof label, "RENDER_TARGET_%u", i); json.beginMember(label); json.writeImage(image); json.endMember(); // RENDER_TARGET_* delete image; } pRenderTargetViews[i]->Release(); } if (pDepthStencilView) { image::Image *image; image = getDepthStencilViewImage(pDevice, pDepthStencilView); if (image) { json.beginMember("DEPTH_STENCIL"); json.writeImage(image); json.endMember(); delete image; } pDepthStencilView->Release(); } json.endObject(); json.endMember(); // framebuffer }
/** * 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(); }
static void dumpShaders(JSONWriter &json, ID3D11DeviceContext *pDeviceContext) { json.beginMember("shaders"); json.beginObject(); com_ptr<ID3D11VertexShader> pVertexShader; pDeviceContext->VSGetShader(&pVertexShader, NULL, NULL); if (pVertexShader) { dumpShader<ID3D11DeviceChild>(json, "VS", pVertexShader); } com_ptr<ID3D11HullShader> pHullShader; pDeviceContext->HSGetShader(&pHullShader, NULL, NULL); if (pHullShader) { dumpShader<ID3D11DeviceChild>(json, "HS", pHullShader); } com_ptr<ID3D11DomainShader> pDomainShader; pDeviceContext->DSGetShader(&pDomainShader, NULL, NULL); if (pDomainShader) { dumpShader<ID3D11DeviceChild>(json, "DS", pDomainShader); } com_ptr<ID3D11GeometryShader> pGeometryShader; pDeviceContext->GSGetShader(&pGeometryShader, NULL, NULL); if (pGeometryShader) { dumpShader<ID3D11DeviceChild>(json, "GS", pGeometryShader); } com_ptr<ID3D11PixelShader> pPixelShader; pDeviceContext->PSGetShader(&pPixelShader, NULL, NULL); if (pPixelShader) { dumpShader<ID3D11DeviceChild>(json, "PS", pPixelShader); } json.endObject(); json.endMember(); // shaders }
void dumpFramebuffer(JSONWriter &json, IDirect3DDevice7 *pDevice) { HRESULT hr; json.beginMember("framebuffer"); json.beginObject(); com_ptr<IDirectDrawSurface7> pRenderTarget; hr = pDevice->GetRenderTarget(&pRenderTarget); if (SUCCEEDED(hr) && pRenderTarget) { image::Image *image; image = getSurfaceImage(pDevice, pRenderTarget); if (image) { json.beginMember("RENDER_TARGET_0"); json.writeImage(image); json.endMember(); // RENDER_TARGET_* } // Search for a depth-stencil attachment DDSCAPS2 ddsCaps; ZeroMemory(&ddsCaps, sizeof ddsCaps); ddsCaps.dwCaps = DDSCAPS_ZBUFFER; com_ptr<IDirectDrawSurface7> pDepthStencil; hr = pRenderTarget->GetAttachedSurface(&ddsCaps, &pDepthStencil); if (SUCCEEDED(hr) && pDepthStencil) { std::cerr << "found ZS!!\n"; image = getSurfaceImage(pDevice, pDepthStencil); if (image) { json.beginMember("DEPTH_STENCIL"); json.writeImage(image); json.endMember(); // DEPTH_STENCIL } } } json.endObject(); json.endMember(); // framebuffer }
static void dumpShaders(JSONWriter &json, IDirect3DDevice9 *pDevice) { json.beginMember("shaders"); HRESULT hr; json.beginObject(); com_ptr<IDirect3DVertexShader9> pVertexShader; hr = pDevice->GetVertexShader(&pVertexShader); if (SUCCEEDED(hr)) { dumpShader<IDirect3DVertexShader9>(json, "vertex", pVertexShader); } com_ptr<IDirect3DPixelShader9> pPixelShader; hr = pDevice->GetPixelShader(&pPixelShader); if (SUCCEEDED(hr)) { dumpShader<IDirect3DPixelShader9>(json, "pixel", pPixelShader); } json.endObject(); json.endMember(); // shaders }
static inline void dumpTextureImage(JSONWriter &json, GLenum target, GLint level) { GLint width, height = 1, depth = 1; width = 0; glGetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &width); if (target != GL_TEXTURE_1D) { height = 0; glGetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &height); if (target == GL_TEXTURE_3D) { depth = 0; glGetTexLevelParameteriv(target, level, GL_TEXTURE_DEPTH, &depth); } } if (width <= 0 || height <= 0 || depth <= 0) { return; } else { char label[512]; GLint active_texture = GL_TEXTURE0; glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); snprintf(label, sizeof label, "%s, %s, level = %i", enumToString(active_texture), enumToString(target), level); json.beginMember(label); 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__", depth); // 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__", 4); GLubyte *pixels = new GLubyte[depth*width*height*4]; resetPixelPackState(); glGetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, pixels); restorePixelPackState(); json.beginMember("__data__"); char *pngBuffer; int pngBufferSize; Image::writePixelsToBuffer(pixels, width, height, 4, false, &pngBuffer, &pngBufferSize); json.writeBase64(pngBuffer, pngBufferSize); free(pngBuffer); json.endMember(); // __data__ delete [] pixels; json.endObject(); } }
static inline void dumpTransformFeedback(JSONWriter &json, GLint program) { GLint transform_feedback_varyings = 0; glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &transform_feedback_varyings); if (!transform_feedback_varyings) { return; } GLint max_name_length = 0; glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_name_length); std::vector<GLchar> name(max_name_length); GLint buffer_mode = GL_INTERLEAVED_ATTRIBS; glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &buffer_mode); std::vector<TransformFeedbackAttrib> attribs(transform_feedback_varyings); // Calculate the offsets and strides of each attribute according to // the value of GL_TRANSFORM_FEEDBACK_BUFFER_MODE GLsizei cum_attrib_offset = 0; for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; GLsizei length = 0; GLsizei size = 0; GLenum type = GL_NONE; glGetTransformFeedbackVarying(program, slot, max_name_length, &length, &size, &type, &name[0]); attrib.name = &name[0]; const AttribDesc & desc = attrib.desc = AttribDesc(type, size); if (!desc) { return; } attrib.size = desc.arrayStride; switch (buffer_mode) { case GL_INTERLEAVED_ATTRIBS: attrib.offset = cum_attrib_offset; break; case GL_SEPARATE_ATTRIBS: attrib.offset = 0; attrib.stride = desc.arrayStride; break; default: assert(0); attrib.offset = 0; attrib.stride = 0; } cum_attrib_offset += desc.arrayStride; } if (buffer_mode == GL_INTERLEAVED_ATTRIBS) { for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; attrib.stride = cum_attrib_offset; } } GLint previous_tbo = 0; glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &previous_tbo); // Map the buffers and calculate how many vertices can they hold // XXX: We currently limit to 1024, or things can get significantly slow. unsigned numVertices = 16*1024; for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; attrib.map = NULL; if (slot == 0 || buffer_mode != GL_INTERLEAVED_ATTRIBS) { GLint tbo = 0; glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, slot, &tbo); if (!tbo) { numVertices = 0; continue; } GLint start = 0; glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_START, slot, &start); GLint size = 0; glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, slot, &size); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo); if (size == 0) { glGetBufferParameteriv(GL_TRANSFORM_FEEDBACK_BUFFER, GL_BUFFER_SIZE, &size); assert(size >= start); size -= start; } unsigned numAttribVertices = calcNumElements(size, attrib.offset, attrib.size, attrib.stride); numVertices = std::min(numVertices, numAttribVertices); attrib.map = (const GLbyte *)glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY) + start; } else { attrib.map = attribs[0].map; } } // Actually dump the vertices json.beginMember("GL_TRANSFORM_FEEDBACK"); json.beginArray(); for (unsigned vertex = 0; vertex < numVertices; ++vertex) { json.beginObject(); for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; if (!attrib.map) { continue; } const AttribDesc & desc = attrib.desc; assert(desc); const GLbyte *vertex_data = attrib.map + attrib.stride*vertex + attrib.offset; dumpAttribArray(json, attrib.name, desc, vertex_data); } json.endObject(); } json.endArray(); json.endMember(); // Unmap the buffers for (GLint slot = 0; slot < transform_feedback_varyings; ++slot) { TransformFeedbackAttrib & attrib = attribs[slot]; if (slot == 0 || buffer_mode != GL_INTERLEAVED_ATTRIBS) { if (!attrib.map) { continue; } GLint tbo = 0; glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, slot, &tbo); assert(tbo); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo); glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER); } } glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, previous_tbo); }
void dumpShadersUniforms(JSONWriter &json, Context &context) { GLint pipeline = 0; GLint vertex_program = 0; GLint fragment_program = 0; GLint geometry_program = 0; GLint tess_control_program = 0; GLint tess_evaluation_program = 0; GLint compute_program = 0; if (!context.ES) { glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING, &pipeline); if (pipeline) { glGetProgramPipelineiv(pipeline, GL_VERTEX_SHADER, &vertex_program); glGetProgramPipelineiv(pipeline, GL_FRAGMENT_SHADER, &fragment_program); glGetProgramPipelineiv(pipeline, GL_GEOMETRY_SHADER, &geometry_program); glGetProgramPipelineiv(pipeline, GL_TESS_CONTROL_SHADER, &tess_control_program); glGetProgramPipelineiv(pipeline, GL_TESS_EVALUATION_SHADER, &tess_evaluation_program); glGetProgramPipelineiv(pipeline, GL_COMPUTE_SHADER, &compute_program); } } GLint program = 0; if (!pipeline) { glGetIntegerv(GL_CURRENT_PROGRAM, &program); } json.beginMember("shaders"); json.beginObject(); if (pipeline) { dumpProgram(json, vertex_program); dumpProgram(json, fragment_program); dumpProgram(json, geometry_program); dumpProgram(json, tess_control_program); dumpProgram(json, tess_evaluation_program); dumpProgram(json, compute_program); } else if (program) { dumpProgram(json, program); } else { dumpArbProgram(json, GL_FRAGMENT_PROGRAM_ARB); dumpArbProgram(json, GL_VERTEX_PROGRAM_ARB); } json.endObject(); json.endMember(); // shaders json.beginMember("uniforms"); json.beginObject(); if (pipeline) { dumpProgramUniformsStage(json, vertex_program, "GL_VERTEX_SHADER"); dumpProgramUniformsStage(json, fragment_program, "GL_FRAGMENT_SHADER"); dumpProgramUniformsStage(json, geometry_program, "GL_GEOMETRY_SHADER"); dumpProgramUniformsStage(json, tess_control_program, "GL_TESS_CONTROL_SHADER"); dumpProgramUniformsStage(json, tess_evaluation_program, "GL_TESS_EVALUATION_SHADER"); dumpProgramUniformsStage(json, compute_program, "GL_COMPUTE_SHADER"); } else if (program) { dumpProgramUniforms(json, program); } else { dumpArbProgramUniforms(json, GL_FRAGMENT_PROGRAM_ARB, "fp."); dumpArbProgramUniforms(json, GL_VERTEX_PROGRAM_ARB, "vp."); } json.endObject(); json.endMember(); // uniforms json.beginMember("buffers"); json.beginObject(); if (program) { dumpTransformFeedback(json, program); } json.endObject(); json.endMember(); // buffers }
static inline void dumpActiveTextureLevel(JSONWriter &json, Context &context, GLenum target, GLint level) { ImageDesc desc; if (!getActiveTextureLevelDesc(context, target, level, desc)) { return; } char label[512]; GLint active_texture = GL_TEXTURE0; glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture); snprintf(label, sizeof label, "%s, %s, level = %d", enumToString(active_texture), enumToString(target), level); json.beginMember(label); json.beginObject(); GLuint channels; GLenum format; if (!context.ES && isDepthFormat(desc.internalFormat)) { format = GL_DEPTH_COMPONENT; channels = 1; } else { format = GL_RGBA; channels = 4; } // Tell the GUI this is no ordinary object, but an image json.writeStringMember("__class__", "image"); json.writeNumberMember("__width__", desc.width); json.writeNumberMember("__height__", desc.height); json.writeNumberMember("__depth__", desc.depth); json.writeStringMember("__format__", enumToString(desc.internalFormat)); // 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[desc.depth*desc.width*desc.height*channels]; context.resetPixelPackState(); if (context.ES) { getTexImageOES(target, level, desc, pixels); } else { glGetTexImage(target, level, format, GL_UNSIGNED_BYTE, pixels); } context.restorePixelPackState(); json.beginMember("__data__"); char *pngBuffer; int pngBufferSize; image::writePixelsToBuffer(pixels, desc.width, desc.height, channels, true, &pngBuffer, &pngBufferSize); json.writeBase64(pngBuffer, pngBufferSize); free(pngBuffer); json.endMember(); // __data__ delete [] pixels; json.endObject(); }
void dumpFramebuffer(JSONWriter &json, Context &context) { json.beginMember("framebuffer"); json.beginObject(); GLint boundDrawFbo = 0, boundReadFbo = 0; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundDrawFbo); glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFbo); if (!boundDrawFbo) { dumpDrawableImages(json, context); } else if (context.ES) { dumpFramebufferAttachments(json, context, GL_FRAMEBUFFER); } else { GLint colorRb = 0, stencilRb = 0, depthRb = 0; GLint draw_buffer0 = GL_NONE; glGetIntegerv(GL_DRAW_BUFFER0, &draw_buffer0); bool multisample = false; GLint boundRb = 0; glGetIntegerv(GL_RENDERBUFFER_BINDING, &boundRb); GLint object_type; glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, draw_buffer0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type); if (object_type == GL_RENDERBUFFER) { glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, draw_buffer0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &colorRb); glBindRenderbuffer(GL_RENDERBUFFER, colorRb); GLint samples = 0; glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); if (samples) { multisample = true; } } glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type); if (object_type == GL_RENDERBUFFER) { glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthRb); glBindRenderbuffer(GL_RENDERBUFFER, depthRb); GLint samples = 0; glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); if (samples) { multisample = true; } } glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &object_type); if (object_type == GL_RENDERBUFFER) { glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &stencilRb); glBindRenderbuffer(GL_RENDERBUFFER, stencilRb); GLint samples = 0; glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); if (samples) { multisample = true; } } glBindRenderbuffer(GL_RENDERBUFFER, boundRb); GLuint rbs[3]; GLint numRbs = 0; GLuint fboCopy = 0; if (multisample) { // glReadPixels doesnt support multisampled buffers so we need // to blit the fbo to a temporary one fboCopy = downsampledFramebuffer(context, boundDrawFbo, draw_buffer0, colorRb, depthRb, stencilRb, rbs, &numRbs); } dumpFramebufferAttachments(json, context, GL_DRAW_FRAMEBUFFER); if (multisample) { glBindRenderbuffer(GL_RENDERBUFFER_BINDING, boundRb); glDeleteRenderbuffers(numRbs, rbs); glDeleteFramebuffers(1, &fboCopy); } glBindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundDrawFbo); } json.endObject(); json.endMember(); // framebuffer }