void DrawingBuffer::initialize(const IntSize& size) { ASSERT(m_context); m_attributes = m_context->getContextAttributes(); if (m_attributes.alpha) { m_internalColorFormat = GraphicsContext3D::RGBA; m_colorFormat = GraphicsContext3D::RGBA; m_internalRenderbufferFormat = Extensions3D::RGBA8_OES; } else { m_internalColorFormat = GraphicsContext3D::RGB; m_colorFormat = GraphicsContext3D::RGB; m_internalRenderbufferFormat = Extensions3D::RGB8_OES; } m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize); m_fbo = m_context->createFramebuffer(); if (m_separateFrontTexture) m_frontColorBuffer = createColorTexture(); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_colorBuffer = createColorTexture(); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); createSecondaryBuffers(); reset(size); #if ENABLE(CANVAS_USES_MAILBOX) m_lastColorBuffer = createNewMailbox(m_colorBuffer); #endif // ENABLE(CANVAS_USES_MAILBOX) }
void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer) { if (!m_context || !m_context->makeContextCurrent() || m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR) return; Extensions3D* extensions = m_context->getExtensions(); #if ENABLE(CANVAS_USES_MAILBOX) // Since the m_frontColorBuffer was produced and sent to the compositor, it cannot be bound to an fbo. // We have to make a copy of it here and bind that copy instead. unsigned sourceTexture = createColorTexture(m_size); extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_frontColorBuffer, sourceTexture, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE); #else // FIXME: Re-examine general correctness of this code beacause m_colorBuffer may contain a stale copy of the data // that was sent to the compositor at some point in the past. unsigned sourceTexture = frontColorBuffer(); #endif // ENABLE(CANVAS_USES_MAILBOX) // Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding). // FIXME: The WebGLRenderingContext tracks the current framebuffer binding, it would be slightly more efficient to use this value // rather than querying it off of the context. GC3Dint previousFramebuffer = 0; m_context->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &previousFramebuffer); Platform3DObject framebuffer = m_context->createFramebuffer(); m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, sourceTexture, 0); extensions->paintFramebufferToCanvas(framebuffer, size().width(), size().height(), !m_attributes.premultipliedAlpha, imageBuffer); m_context->deleteFramebuffer(framebuffer); #if ENABLE(CANVAS_USES_MAILBOX) m_context->deleteTexture(sourceTexture); #endif // ENABLE(CANVAS_USES_MAILBOX) m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, previousFramebuffer); }
bool DrawingBuffer::prepareMailbox(WebKit::WebExternalTextureMailbox* outMailbox) { if (!m_context || !m_contentsChanged || !m_lastColorBuffer) return false; m_context->makeContextCurrent(); // Resolve the multisampled buffer into the texture referenced by m_lastColorBuffer mailbox. if (multisample()) commit(); // We must restore the texture binding since creating new textures, // consuming and producing mailboxes changes it. ScopedTextureUnit0BindingRestorer restorer(m_context.get(), m_activeTextureUnit, m_texture2DBinding); // First try to recycle an old buffer. RefPtr<MailboxInfo> nextFrontColorBuffer = getRecycledMailbox(); // No buffer available to recycle, create a new one. if (!nextFrontColorBuffer) { unsigned newColorBuffer = createColorTexture(m_size); // Bad things happened, abandon ship. if (!newColorBuffer) return false; nextFrontColorBuffer = createNewMailbox(newColorBuffer); } if (m_preserveDrawingBuffer == Discard) { m_colorBuffer = nextFrontColorBuffer->textureId; swap(nextFrontColorBuffer, m_lastColorBuffer); // It appears safe to overwrite the context's framebuffer binding in the Discard case since there will always be a // WebGLRenderingContext::clearIfComposited() call made before the next draw call which restores the framebuffer binding. // If this stops being true at some point, we should track the current framebuffer binding in the DrawingBuffer and restore // it after attaching the new back buffer here. m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); } else { Extensions3D* extensions = m_context->getExtensions(); extensions->copyTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, m_colorBuffer, nextFrontColorBuffer->textureId, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE); } if (multisample() && !m_framebufferBinding) bind(); else restoreFramebufferBinding(); m_contentsChanged = false; context()->bindTexture(GraphicsContext3D::TEXTURE_2D, nextFrontColorBuffer->textureId); context()->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, nextFrontColorBuffer->mailbox.name); context()->flush(); m_context->markLayerComposited(); *outMailbox = nextFrontColorBuffer->mailbox; m_frontColorBuffer = nextFrontColorBuffer->textureId; return true; }
DrawingBuffer::TextureInfo DrawingBuffer::createDefaultTextureAndAllocateMemory(const IntSize& size) { TextureParameters parameters = defaultTextureParameters(); GLuint textureId = createColorTexture(parameters); texImage2DResourceSafe(parameters.target, 0, parameters.creationInternalColorFormat, size.width(), size.height(), 0, parameters.colorFormat, GL_UNSIGNED_BYTE); DrawingBuffer::TextureInfo info; info.textureId = textureId; info.parameters = parameters; return info; }
void DrawingBuffer::initialize(const IntSize& size) { ASSERT(m_context); m_attributes = m_context->getContextAttributes(); Extensions3DUtil extensionsUtil(m_context); if (m_attributes.alpha) { m_internalColorFormat = GL_RGBA; m_colorFormat = GL_RGBA; m_internalRenderbufferFormat = GL_RGBA8_OES; } else { m_internalColorFormat = GL_RGB; m_colorFormat = GL_RGB; m_internalRenderbufferFormat = GL_RGB8_OES; } m_context->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); int maxSampleCount = 0; m_multisampleMode = None; if (m_attributes.antialias && m_multisampleExtensionSupported) { m_context->getIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSampleCount); m_multisampleMode = ExplicitResolve; if (extensionsUtil.supportsExtension("GL_EXT_multisampled_render_to_texture")) m_multisampleMode = ImplicitResolve; } m_sampleCount = std::min(4, maxSampleCount); m_fbo = m_context->createFramebuffer(); m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); m_colorBuffer = createColorTexture(); if (m_multisampleMode == ImplicitResolve) m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0, m_sampleCount); else m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0); createSecondaryBuffers(); reset(size); }
DrawingBuffer::TextureInfo DrawingBuffer::createTextureAndAllocateMemory(const IntSize& size) { if (!RuntimeEnabledFeatures::webGLImageChromiumEnabled()) return createDefaultTextureAndAllocateMemory(size); // First, try to allocate a CHROMIUM_image. This always has the potential to // fail. TextureParameters parameters = chromiumImageTextureParameters(); GLuint imageId = m_gl->CreateGpuMemoryBufferImageCHROMIUM(size.width(), size.height(), parameters.creationInternalColorFormat, GC3D_SCANOUT_CHROMIUM); if (!imageId) return createDefaultTextureAndAllocateMemory(size); GLuint textureId = createColorTexture(parameters); m_gl->BindTexImage2DCHROMIUM(parameters.target, imageId); TextureInfo info; info.textureId = textureId; info.imageId = imageId; info.parameters = parameters; clearChromiumImageAlpha(info); return info; }
void DrawingBuffer::paintCompositedResultsToCanvas(ImageBuffer* imageBuffer) { if (!m_context || !m_context->makeContextCurrent() || m_context->getGraphicsResetStatusARB() != GL_NO_ERROR) return; if (!imageBuffer) return; Platform3DObject tex = imageBuffer->getBackingTexture(); if (tex) { m_context->copyTextureCHROMIUM(GL_TEXTURE_2D, m_frontColorBuffer, tex, 0, GL_RGBA, GL_UNSIGNED_BYTE); return; } // Since the m_frontColorBuffer was produced and sent to the compositor, it cannot be bound to an fbo. // We have to make a copy of it here and bind that copy instead. // FIXME: That's not true any more, provided we don't change texture // parameters. unsigned sourceTexture = createColorTexture(m_size); m_context->copyTextureCHROMIUM(GL_TEXTURE_2D, m_frontColorBuffer, sourceTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE); // Since we're using the same context as WebGL, we have to restore any state we change (in this case, just the framebuffer binding). // FIXME: The WebGLRenderingContext tracks the current framebuffer binding, it would be slightly more efficient to use this value // rather than querying it off of the context. GLint previousFramebuffer = 0; m_context->getIntegerv(GL_FRAMEBUFFER_BINDING, &previousFramebuffer); Platform3DObject framebuffer = m_context->createFramebuffer(); m_context->bindFramebuffer(GL_FRAMEBUFFER, framebuffer); m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sourceTexture, 0); paintFramebufferToCanvas(framebuffer, size().width(), size().height(), !m_attributes.premultipliedAlpha, imageBuffer); m_context->deleteFramebuffer(framebuffer); m_context->deleteTexture(sourceTexture); m_context->bindFramebuffer(GL_FRAMEBUFFER, previousFramebuffer); }
bool DrawingBuffer::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox, blink::WebExternalBitmap* bitmap) { if (!m_context || !m_contentsChanged) return false; m_context->makeContextCurrent(); // Resolve the multisampled buffer into m_colorBuffer texture. if (m_multisampleMode != None) commit(); if (bitmap) { bitmap->setSize(size()); unsigned char* pixels = bitmap->pixels(); bool needPremultiply = m_attributes.alpha && !m_attributes.premultipliedAlpha; WebGLImageConversion::AlphaOp op = needPremultiply ? WebGLImageConversion::AlphaDoPremultiply : WebGLImageConversion::AlphaDoNothing; if (pixels) readBackFramebuffer(pixels, size().width(), size().height(), ReadbackSkia, op); } // We must restore the texture binding since creating new textures, // consuming and producing mailboxes changes it. ScopedTextureUnit0BindingRestorer restorer(m_context, m_activeTextureUnit, m_texture2DBinding); // First try to recycle an old buffer. RefPtr<MailboxInfo> frontColorBufferMailbox = recycledMailbox(); // No buffer available to recycle, create a new one. if (!frontColorBufferMailbox) { unsigned newColorBuffer = createColorTexture(m_size); // Bad things happened, abandon ship. if (!newColorBuffer) return false; frontColorBufferMailbox = createNewMailbox(newColorBuffer); } if (m_preserveDrawingBuffer == Discard) { swap(frontColorBufferMailbox->textureId, m_colorBuffer); // It appears safe to overwrite the context's framebuffer binding in the Discard case since there will always be a // WebGLRenderingContext::clearIfComposited() call made before the next draw call which restores the framebuffer binding. // If this stops being true at some point, we should track the current framebuffer binding in the DrawingBuffer and restore // it after attaching the new back buffer here. m_context->bindFramebuffer(GL_FRAMEBUFFER, m_fbo); if (m_multisampleMode == ImplicitResolve) m_context->framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0, m_sampleCount); else m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0); } else { m_context->copyTextureCHROMIUM(GL_TEXTURE_2D, m_colorBuffer, frontColorBufferMailbox->textureId, 0, GL_RGBA, GL_UNSIGNED_BYTE); } if (m_multisampleMode != None && !m_framebufferBinding) bind(); else restoreFramebufferBinding(); m_contentsChanged = false; m_context->bindTexture(GL_TEXTURE_2D, frontColorBufferMailbox->textureId); m_context->produceTextureCHROMIUM(GL_TEXTURE_2D, frontColorBufferMailbox->mailbox.name); m_context->flush(); frontColorBufferMailbox->mailbox.syncPoint = m_context->insertSyncPoint(); markLayerComposited(); *outMailbox = frontColorBufferMailbox->mailbox; m_frontColorBuffer = frontColorBufferMailbox->textureId; return true; }
void RenderBlock:: beginVboRendering(BlockLayout block_size) { GlException_CHECK_ERROR(); //unsigned meshW = collection->samples_per_block(); //unsigned meshH = collection->scales_per_block(); createColorTexture(24); // These will be linearly interpolated when rendering, so a high resolution texture is not needed glActiveTexture(GL_TEXTURE2); _colorTexture->bindTexture2D(); glActiveTexture(GL_TEXTURE0); glUseProgram(_shader_prog); // TODO check if this takes any time { // Set default uniform variables parameters for the vertex and pixel shader TIME_RENDERER_BLOCKS TaskTimer tt("Setting shader parameters"); GLuint uniVertText0, uniVertText2, uniColorTextureFactor, uniFixedColor, uniClearColor, uniContourPlot, uniFlatness, uniYScale, uniYOffset, uniLogScale, uniScaleTex, uniOffsTex; uniVertText0 = glGetUniformLocation(_shader_prog, "tex"); glUniform1i(uniVertText0, 0); // GL_TEXTURE0 + i // uniVertText1 = glGetUniformLocation(_shader_prog, "tex_nearest"); // glUniform1i(uniVertText1, _mesh_width*_mesh_height>4 ? 0 : 0); uniVertText2 = glGetUniformLocation(_shader_prog, "tex_color"); glUniform1i(uniVertText2, 2); uniFixedColor = glGetUniformLocation(_shader_prog, "fixedColor"); switch (render_settings->color_mode) { case RenderSettings::ColorMode_Grayscale: glUniform4f(uniFixedColor, 0.f, 0.f, 0.f, 0.f); break; case RenderSettings::ColorMode_BlackGrayscale: glUniform4f(uniFixedColor, 1.f, 1.f, 1.f, 0.f); break; default: { tvector<4, float> fixed_color = render_settings->fixed_color; glUniform4f(uniFixedColor, fixed_color[0], fixed_color[1], fixed_color[2], fixed_color[3]); break; } } uniClearColor = glGetUniformLocation(_shader_prog, "clearColor"); tvector<4, float> clear_color = render_settings->clear_color; glUniform4f(uniClearColor, clear_color[0], clear_color[1], clear_color[2], clear_color[3]); uniColorTextureFactor = glGetUniformLocation(_shader_prog, "colorTextureFactor"); switch(render_settings->color_mode) { case RenderSettings::ColorMode_Rainbow: case RenderSettings::ColorMode_GreenRed: case RenderSettings::ColorMode_GreenWhite: case RenderSettings::ColorMode_Green: glUniform1f(uniColorTextureFactor, 1.f); break; default: glUniform1f(uniColorTextureFactor, 0.f); break; } uniContourPlot = glGetUniformLocation(_shader_prog, "contourPlot"); glUniform1f(uniContourPlot, render_settings->draw_contour_plot ? 1.f : 0.f ); uniFlatness = glGetUniformLocation(_shader_prog, "flatness"); float v = render_settings->draw_flat ? 0 : 2*render_settings->last_ysize; // as glScalef in setupGlStates glUniform1f(uniFlatness, v); uniYScale = glGetUniformLocation(_shader_prog, "yScale"); glUniform1f(uniYScale, render_settings->y_scale); uniYOffset = glGetUniformLocation(_shader_prog, "yOffset"); glUniform1f(uniYOffset, render_settings->y_offset); // yOffset specifies 'b' which says which 'v' that should render as 0 // yOffset=-1 => v>1 => fragColor>0 // yOffset=0 => v>L => fragColor>0 // yOffset=1 => v>0 => fragColor>0 float L = 0.00001; float tb = 1.0/L - 1.0; float tc = L/(1.0 - tb); float ta = L - tc; float b = ta * exp(-render_settings->y_offset * log(tb)) + tc; // yScale specifies which intensity 'v=1' should have // v<1 => fragColor < yScale // v=1 => fragColor = yScale // v>1 => fragColor > yScale float x1 = render_settings->y_scale / (log(1.0) - log(b)); float x2 = - log(b) * x1; uniLogScale = glGetUniformLocation(_shader_prog, "logScale"); glUniform3f(uniLogScale, render_settings->log_scale, x1, x2); float w = block_size.texels_per_row (), h = block_size.texels_per_column (); uniScaleTex = glGetUniformLocation(_shader_prog, "scale_tex"); glUniform2f(uniScaleTex, (w-1.f)/w, (h-1.f)/h); uniOffsTex = glGetUniformLocation(_shader_prog, "offset_tex"); glUniform2f(uniOffsTex, .5f/w, .5f/h); } glBindBuffer(GL_ARRAY_BUFFER, *_mesh_position); glVertexPointer(4, GL_FLOAT, 0, 0); glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _mesh_index_buffer); GlException_CHECK_ERROR(); }