// Sets the coordinate range of content that ends being drawn onto the target render surface. // The target render surface is assumed to have an origin at 0, 0 and the width and height of // of the drawRect. void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY) { if (flipY) m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y()); else m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY()); GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height())); }
void OverlayRenderer::render(RenderContext& context, const float viewWidth, const float viewHeight) { if (m_vbo == NULL) m_vbo = new Vbo(GL_ARRAY_BUFFER, 0xFFFF); if (m_compass == NULL) m_compass = new CompassRenderer(); glClear(GL_DEPTH_BUFFER_BIT); const Mat4f projection = orthoMatrix(0.0f, 1000.0f, -viewWidth / 2.0f, viewHeight / 2.0f, viewWidth / 2.0f, -viewHeight / 2.0f); const Mat4f view = viewMatrix(Vec3f::PosY, Vec3f::PosZ) * translationMatrix(500.0f * Vec3f::PosY); Renderer::ApplyTransformation ortho(context.transformation(), projection, view); const Mat4f compassTransformation = translationMatrix(Vec3f(-viewWidth / 2.0f + 50.0f, 0.0f, -viewHeight / 2.0f + 50.0f)) * scalingMatrix(2.0f); Renderer::ApplyModelMatrix applyCompassTranslate(context.transformation(), compassTransformation); m_compass->render(*m_vbo, context); }
void Compass::doRender(RenderContext& renderContext) { const Camera& camera = renderContext.camera(); const Camera::Viewport& viewport = camera.unzoomedViewport(); const int viewWidth = viewport.width; const int viewHeight = viewport.height; const Mat4x4f projection = orthoMatrix(0.0f, 1000.0f, -viewWidth / 2.0f, viewHeight / 2.0f, viewWidth / 2.0f, -viewHeight / 2.0f); const Mat4x4f view = viewMatrix(Vec3f::PosY, Vec3f::PosZ) * translationMatrix(500.0f * Vec3f::PosY); const ReplaceTransformation ortho(renderContext.transformation(), projection, view); const Mat4x4f compassTransformation = translationMatrix(Vec3f(-viewWidth / 2.0f + 55.0f, 0.0f, -viewHeight / 2.0f + 55.0f)) * scalingMatrix<4>(2.0f); const MultiplyModelMatrix compass(renderContext.transformation(), compassTransformation); const Mat4x4f cameraTransformation = cameraRotationMatrix(camera); glAssert(glClear(GL_DEPTH_BUFFER_BIT)); renderBackground(renderContext); glAssert(glClear(GL_DEPTH_BUFFER_BIT)); doRenderCompass(renderContext, cameraTransformation); }
// Updates the contents of the root layer texture that fall inside the updateRect // and re-composits all sublayers. void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition) { ASSERT(m_hardwareCompositing); if (!m_rootLayer) return; makeContextCurrent(); GLC(glBindTexture(GL_TEXTURE_2D, m_rootLayerTextureId)); // If the size of the visible area has changed then allocate a new texture // to store the contents of the root layer and adjust the projection matrix // and viewport. int visibleRectWidth = visibleRect.width(); int visibleRectHeight = visibleRect.height(); if (visibleRectWidth != m_rootLayerTextureWidth || visibleRectHeight != m_rootLayerTextureHeight) { m_rootLayerTextureWidth = visibleRect.width(); m_rootLayerTextureHeight = visibleRect.height(); m_projectionMatrix = orthoMatrix(0, visibleRectWidth, visibleRectHeight, 0, -1000, 1000); GLC(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0)); } // The GL viewport covers the entire visible area, including the scrollbars. GLC(glViewport(0, 0, visibleRectWidth, visibleRectHeight)); // Bind the common vertex attributes used for drawing all the layers. LayerChromium::prepareForDraw(layerSharedValues()); // FIXME: These calls can be made once, when the compositor context is initialized. GLC(glDisable(GL_DEPTH_TEST)); GLC(glDisable(GL_CULL_FACE)); GLC(glDepthFunc(GL_LEQUAL)); GLC(glClearStencil(0)); if (m_scrollPosition == IntPoint(-1, -1)) m_scrollPosition = scrollPosition; IntPoint scrollDelta = toPoint(scrollPosition - m_scrollPosition); // Scroll only when the updateRect contains pixels for the newly uncovered region to avoid flashing. if ((scrollDelta.x() && updateRect.width() >= abs(scrollDelta.x()) && updateRect.height() >= contentRect.height()) || (scrollDelta.y() && updateRect.height() >= abs(scrollDelta.y()) && updateRect.width() >= contentRect.width())) { // Scrolling works as follows: We render a quad with the current root layer contents // translated by the amount the page has scrolled since the last update and then read the // pixels of the content area (visible area excluding the scroll bars) back into the // root layer texture. The newly exposed area is subesquently filled as usual with // the contents of the updateRect. TransformationMatrix scrolledLayerMatrix; #if PLATFORM(SKIA) float scaleFactor = 1.0f; #elif PLATFORM(CG) // Because the contents of the OpenGL texture are inverted // vertically compared to the Skia backend, we need to move // the backing store in the opposite direction. float scaleFactor = -1.0f; #else #error "Need to implement for your platform." #endif scrolledLayerMatrix.translate3d(0.5 * visibleRect.width() - scrollDelta.x(), 0.5 * visibleRect.height() + scaleFactor * scrollDelta.y(), 0); scrolledLayerMatrix.scale3d(1, -1, 1); useShader(m_scrollShaderProgram); GLC(glUniform1i(m_scrollShaderSamplerLocation, 0)); LayerChromium::drawTexturedQuad(m_projectionMatrix, scrolledLayerMatrix, visibleRect.width(), visibleRect.height(), 1, m_scrollShaderMatrixLocation, -1); GLC(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height())); m_scrollPosition = scrollPosition; } else if (abs(scrollDelta.y()) > contentRect.height() || abs(scrollDelta.x()) > contentRect.width()) { // Scrolling larger than the contentRect size does not preserve any of the pixels, so there is // no need to copy framebuffer pixels back into the texture. m_scrollPosition = scrollPosition; } // FIXME: The following check should go away when the compositor renders independently from its own thread. // Ignore a 1x1 update rect at (0, 0) as that's used a way to kick off a redraw for the compositor. if (!(!updateRect.x() && !updateRect.y() && updateRect.width() == 1 && updateRect.height() == 1)) { // Update the root layer texture. ASSERT((updateRect.x() + updateRect.width() <= m_rootLayerTextureWidth) && (updateRect.y() + updateRect.height() <= m_rootLayerTextureHeight)); #if PLATFORM(SKIA) // Get the contents of the updated rect. const SkBitmap bitmap = m_rootLayerCanvas->getDevice()->accessBitmap(false); int rootLayerWidth = bitmap.width(); int rootLayerHeight = bitmap.height(); ASSERT(rootLayerWidth == updateRect.width() && rootLayerHeight == updateRect.height()); void* pixels = bitmap.getPixels(); // Copy the contents of the updated rect to the root layer texture. GLC(glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels)); #elif PLATFORM(CG) // Get the contents of the updated rect. ASSERT(static_cast<int>(CGBitmapContextGetWidth(m_rootLayerCGContext.get())) == updateRect.width() && static_cast<int>(CGBitmapContextGetHeight(m_rootLayerCGContext.get())) == updateRect.height()); void* pixels = m_rootLayerBackingStore.data(); // Copy the contents of the updated rect to the root layer texture. // The origin is at the lower left in Core Graphics' coordinate system. We need to correct for this here. GLC(glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), m_rootLayerTextureHeight - updateRect.y() - updateRect.height(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels)); #else #error "Need to implement for your platform." #endif } glClearColor(0, 0, 1, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Render the root layer using a quad that takes up the entire visible area of the window. // We reuse the shader program used by ContentLayerChromium. const ContentLayerChromium::SharedValues* contentLayerValues = contentLayerSharedValues(); useShader(contentLayerValues->contentShaderProgram()); GLC(glUniform1i(contentLayerValues->shaderSamplerLocation(), 0)); TransformationMatrix layerMatrix; layerMatrix.translate3d(visibleRect.width() * 0.5f, visibleRect.height() * 0.5f, 0); LayerChromium::drawTexturedQuad(m_projectionMatrix, layerMatrix, visibleRect.width(), visibleRect.height(), 1, contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation()); // If culling is enabled then we will cull the backface. GLC(glCullFace(GL_BACK)); // The orthographic projection is setup such that Y starts at zero and // increases going down the page so we need to adjust the winding order of // front facing triangles. GLC(glFrontFace(GL_CW)); // The shader used to render layers returns pre-multiplied alpha colors // so we need to send the blending mode appropriately. GLC(glEnable(GL_BLEND)); GLC(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); // Translate all the composited layers by the scroll position. TransformationMatrix matrix; matrix.translate3d(-m_scrollPosition.x(), -m_scrollPosition.y(), 0); // Traverse the layer tree and update the layer transforms. float opacity = 1; const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers(); size_t i; for (i = 0; i < sublayers.size(); i++) updateLayersRecursive(sublayers[i].get(), matrix, opacity); m_rootVisibleRect = visibleRect; // Enable scissoring to avoid rendering composited layers over the scrollbars. GLC(glEnable(GL_SCISSOR_TEST)); FloatRect scissorRect(contentRect); // The scissorRect should not include the scroll offset. scissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y()); scissorToRect(scissorRect); // Clear the stencil buffer to 0. GLC(glClear(GL_STENCIL_BUFFER_BIT)); // Disable writes to the stencil buffer. GLC(glStencilMask(0)); // Traverse the layer tree one more time to draw the layers. for (i = 0; i < sublayers.size(); i++) drawLayersRecursive(sublayers[i].get(), scissorRect); GLC(glDisable(GL_SCISSOR_TEST)); m_gles2Context->swapBuffers(); m_needsDisplay = false; }