Example #1
0
void CCTextureLayerImpl::willDraw(LayerRendererChromium* layerRenderer)
{
    CCLayerImpl::willDraw(layerRenderer);

    if (m_ioSurfaceChanged) {
        GraphicsContext3D* context = layerRenderer->context();
        Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context->getExtensions());
        ASSERT(extensions->supports("GL_CHROMIUM_iosurface"));
        ASSERT(extensions->supports("GL_ARB_texture_rectangle"));

        if (!m_ioSurfaceTextureId)
            m_ioSurfaceTextureId = context->createTexture();

        GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
        GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId));
        GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
        GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
        GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
        GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
        extensions->texImageIOSurface2DCHROMIUM(Extensions3D::TEXTURE_RECTANGLE_ARB,
                                                m_ioSurfaceSize.width(),
                                                m_ioSurfaceSize.height(),
                                                m_ioSurfaceId,
                                                0);
        // Do not check for error conditions. texImageIOSurface2DCHROMIUM is supposed to hold on to
        // the last good IOSurface if the new one is already closed. This is only a possibility
        // during live resizing of plugins. However, it seems that this is not sufficient to
        // completely guard against garbage being drawn. If this is found to be a significant issue,
        // it may be necessary to explicitly tell the embedder when to free the surfaces it has
        // allocated.
        m_ioSurfaceChanged = false;
    }
}
Example #2
0
void LayerTextureSubImage::uploadWithMapTexSubImage(const uint8_t* image, const IntRect& imageRect,
                                                    const IntRect& sourceRect, const IntRect& destRect,
                                                    GC3Denum format, GraphicsContext3D* context)
{
    TRACE_EVENT("LayerTextureSubImage::uploadWithMapTexSubImage", this, 0);
    // Offset from image-rect to source-rect.
    IntPoint offset(sourceRect.x() - imageRect.x(), sourceRect.y() - imageRect.y());

    // Upload tile data via a mapped transfer buffer
    Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context->getExtensions());
    uint8_t* pixelDest = static_cast<uint8_t*>(extensions->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, destRect.x(), destRect.y(), destRect.width(), destRect.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY));

    if (!pixelDest) {
        uploadWithTexSubImage(image, imageRect, sourceRect, destRect, format, context);
        return;
    }

    if (imageRect.width() == sourceRect.width() && !offset.x())
        memcpy(pixelDest, &image[4 * offset.y() * imageRect.width()], imageRect.width() * destRect.height() * 4);
    else {
        // Strides not equal, so do a row-by-row memcpy from the
        // paint results into the pixelDest
        for (int row = 0; row < destRect.height(); ++row)
            memcpy(&pixelDest[destRect.width() * 4 * row],
                   &image[4 * (offset.x() + (offset.y() + row) * imageRect.width())],
                   destRect.width() * 4);
    }
    extensions->unmapTexSubImage2DCHROMIUM(pixelDest);
}
Example #3
0
void RateLimiter::rateLimitContext(Timer<RateLimiter>*)
{
    TRACE_EVENT("RateLimiter::rateLimitContext", this, 0);

    Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(m_context->getExtensions());

    extensions->rateLimitOffscreenContextCHROMIUM();
}
Example #4
0
void WebGLLayerChromium::rateLimitContext(Timer<WebGLLayerChromium>*)
{
    TRACE_EVENT("WebGLLayerChromium::rateLimitContext", this, 0);

    if (!m_context)
        return;

    Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(m_context->getExtensions());
    extensions->rateLimitOffscreenContextCHROMIUM();
}
Example #5
0
bool WebGLLayerChromium::paintRenderedResultsToCanvas(ImageBuffer* imageBuffer)
{
    if (m_textureUpdated || !layerRendererContext() || !drawsContent())
        return false;

    IntSize framebufferSize = context()->getInternalFramebufferSize();
    ASSERT(layerRendererContext());

    // This would ideally be done in the webgl context, but that isn't possible yet.
    Platform3DObject framebuffer = layerRendererContext()->createFramebuffer();
    layerRendererContext()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
    layerRendererContext()->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_textureId, 0);

    Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(layerRendererContext()->getExtensions());
    extensions->paintFramebufferToCanvas(framebuffer, framebufferSize.width(), framebufferSize.height(), !context()->getContextAttributes().premultipliedAlpha, imageBuffer);
    layerRendererContext()->deleteFramebuffer(framebuffer);
    return true;
}
bool WebGLLayerChromium::paintRenderedResultsToCanvas(ImageBuffer* imageBuffer)
{
    if (!m_drawingBuffer || !drawsContent())
        return false;

    IntSize framebufferSize = context()->getInternalFramebufferSize();

    // 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;
    context()->getIntegerv(GraphicsContext3D::FRAMEBUFFER_BINDING, &previousFramebuffer);

    Platform3DObject framebuffer = context()->createFramebuffer();
    context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
    context()->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_textureId, 0);

    Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context()->getExtensions());
    extensions->paintFramebufferToCanvas(framebuffer, framebufferSize.width(), framebufferSize.height(), !context()->getContextAttributes().premultipliedAlpha, imageBuffer);
    context()->deleteFramebuffer(framebuffer);

    context()->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, previousFramebuffer);
    return true;
}
Example #7
0
void CCHeadsUpDisplay::draw()
{
    GraphicsContext3D* context = m_layerRenderer->context();
    if (!m_hudTexture)
        m_hudTexture = ManagedTexture::create(m_layerRenderer->renderSurfaceTextureManager());

    // Use a fullscreen texture only if we need to...
    IntSize hudSize;
    if (settings().showPlatformLayerTree) {
        hudSize.setWidth(min(2048, m_layerRenderer->viewportWidth()));
        hudSize.setHeight(min(2048, m_layerRenderer->viewportHeight()));
    } else {
        hudSize.setWidth(512);
        hudSize.setHeight(128);
    }

    if (!m_hudTexture->reserve(hudSize, GraphicsContext3D::RGBA))
        return;

    // Render pixels into the texture.
    PlatformCanvas canvas;
    canvas.resize(hudSize);
    {
        PlatformCanvas::Painter painter(&canvas, PlatformCanvas::Painter::GrayscaleText);
        drawHudContents(painter.context(), hudSize);
    }

    // Upload to GL.
    {
        PlatformCanvas::AutoLocker locker(&canvas);

        m_hudTexture->bindTexture(context, m_layerRenderer->renderSurfaceTextureAllocator());
        bool uploadedViaMap = false;
        if (m_useMapSubForUploads) {
            Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context->getExtensions());
            uint8_t* pixelDest = static_cast<uint8_t*>(extensions->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, hudSize.width(), hudSize.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY));

            if (pixelDest) {
                uploadedViaMap = true;
                memcpy(pixelDest, locker.pixels(), hudSize.width() * hudSize.height() * 4);
                extensions->unmapTexSubImage2DCHROMIUM(pixelDest);
            }
        }

        if (!uploadedViaMap) {
            GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, canvas.size().width(), canvas.size().height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, locker.pixels()));
        }
    }

    // Draw the HUD onto the default render surface.
    const Program* program = m_layerRenderer->headsUpDisplayProgram();
    ASSERT(program && program->initialized());
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
    m_hudTexture->bindTexture(context, m_layerRenderer->renderSurfaceTextureAllocator());
    GLC(context, context->useProgram(program->program()));
    GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));

    TransformationMatrix matrix;
    matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0);
    m_layerRenderer->drawTexturedQuad(matrix, hudSize.width(), hudSize.height(),
                                      1.0f, m_layerRenderer->sharedGeometryQuad(), program->vertexShader().matrixLocation(),
                                      program->fragmentShader().alphaLocation(),
                                      -1);
    m_hudTexture->unreserve();
}
void LayerRendererChromium::updateLayers(LayerList& renderSurfaceLayerList)
{
    TRACE_EVENT("LayerRendererChromium::updateLayers", this, 0);
    CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl();

    if (!rootDrawLayer->renderSurface())
        rootDrawLayer->createRenderSurface();
    ASSERT(rootDrawLayer->renderSurface());

    rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), m_viewportVisibleRect.size());

    IntRect rootScissorRect(m_viewportVisibleRect);
    // The scissorRect should not include the scroll offset.
    rootScissorRect.move(-m_viewportScrollPosition.x(), -m_viewportScrollPosition.y());
    rootDrawLayer->setScissorRect(rootScissorRect);

    m_defaultRenderSurface = rootDrawLayer->renderSurface();

    renderSurfaceLayerList.append(rootDrawLayer);

    TransformationMatrix identityMatrix;
    m_defaultRenderSurface->m_layerList.clear();
    // Unfortunately, updatePropertiesAndRenderSurfaces() currently both updates the layers and updates the draw state
    // (transforms, etc). It'd be nicer if operations on the presentation layers happened later, but the draw
    // transforms are needed by large layers to determine visibility. Tiling will fix this by eliminating the
    // concept of a large content layer.
    updatePropertiesAndRenderSurfaces(rootDrawLayer, identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList);

#ifndef NDEBUG
    s_inPaintLayerContents = true;
#endif
    paintLayerContents(renderSurfaceLayerList);
#ifndef NDEBUG
    s_inPaintLayerContents = false;
#endif

    // FIXME: Before updateCompositorResourcesRecursive, when the compositor runs in
    // its own thread, and when the copyTexImage2D bug is fixed, insert
    // a glWaitLatch(Compositor->Offscreen) on all child contexts here instead
    // of after updateCompositorResourcesRecursive.
    // Also uncomment the glSetLatch(Compositor->Offscreen) code in addChildContext.
//  if (hardwareCompositing() && m_contextSupportsLatch) {
//      // For each child context:
//      //   glWaitLatch(Compositor->Offscreen);
//      ChildContextMap::iterator i = m_childContexts.begin();
//      for (; i != m_childContexts.end(); ++i) {
//          Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(i->first->getExtensions());
//          GC3Duint childToParentLatchId, parentToChildLatchId;
//          ext->getParentToChildLatchCHROMIUM(&parentToChildLatchId);
//          ext->waitLatchCHROMIUM(parentToChildLatchId);
//      }
//  }

    updateCompositorResourcesRecursive(m_rootLayer.get());

    // After updateCompositorResourcesRecursive, set/wait latches for all child
    // contexts. This will prevent the compositor from using any of the child
    // parent textures while WebGL commands are executing from javascript *and*
    // while the final parent texture is being blit'd. copyTexImage2D
    // uses the parent texture as a temporary resolve buffer, so that's why the
    // waitLatch is below, to block the compositor from using the parent texture
    // until the next WebGL SwapBuffers (or copyTextureToParentTexture for
    // Canvas2D).
    if (hardwareCompositing() && m_contextSupportsLatch) {
        m_childContextsWereCopied = true;
        // For each child context:
        //   glSetLatch(Offscreen->Compositor);
        //   glWaitLatch(Compositor->Offscreen);
        ChildContextMap::iterator i = m_childContexts.begin();
        for (; i != m_childContexts.end(); ++i) {
            Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(i->first->getExtensions());
            GC3Duint childToParentLatchId, parentToChildLatchId;
            ext->getParentToChildLatchCHROMIUM(&parentToChildLatchId);
            ext->getChildToParentLatchCHROMIUM(&childToParentLatchId);
            ext->setLatchCHROMIUM(childToParentLatchId);
            ext->waitLatchCHROMIUM(parentToChildLatchId);
        }
    }
}
void LayerRendererChromium::updateAndDrawLayers()
{
    // FIXME: use the frame begin time from the overall compositor scheduler.
    // This value is currently inaccessible because it is up in Chromium's
    // RenderWidget.
    m_headsUpDisplay->onFrameBegin(currentTime());
    ASSERT(m_hardwareCompositing);

    if (!m_rootLayer)
        return;

    updateRootLayerContents();

    // Recheck that we still have a root layer. This may become null if
    // compositing gets turned off during a paint operation.
    if (!m_rootLayer)
        return;

    {
        TRACE_EVENT("LayerRendererChromium::synchronizeTrees", this, 0);
        m_rootCCLayerImpl = TreeSynchronizer::synchronizeTrees(m_rootLayer.get(), m_rootCCLayerImpl.get());
    }

    LayerList renderSurfaceLayerList;

    updateLayers(renderSurfaceLayerList);

    // Before drawLayers:
    if (hardwareCompositing() && m_contextSupportsLatch) {
        // FIXME: The multithreaded compositor case will not work as long as
        // copyTexImage2D resolves to the parent texture, because the main
        // thread can execute WebGL calls on the child context at any time,
        // potentially clobbering the parent texture that is being renderered
        // by the compositor thread.
        if (m_childContextsWereCopied) {
            Extensions3DChromium* parentExt = static_cast<Extensions3DChromium*>(m_context->getExtensions());
            // For each child context:
            //   glWaitLatch(Offscreen->Compositor);
            ChildContextMap::iterator i = m_childContexts.begin();
            for (; i != m_childContexts.end(); ++i) {
                Extensions3DChromium* childExt = static_cast<Extensions3DChromium*>(i->first->getExtensions());
                GC3Duint latchId;
                childExt->getChildToParentLatchCHROMIUM(&latchId);
                parentExt->waitLatchCHROMIUM(latchId);
            }
        }
        // Reset to false to indicate that we have consumed the dirty child
        // contexts' parent textures. (This is only useful when the compositor
        // is multithreaded.)
        m_childContextsWereCopied = false;
    }

    drawLayers(renderSurfaceLayerList);

    m_textureManager->unprotectAllTextures();

    // After drawLayers:
    if (hardwareCompositing() && m_contextSupportsLatch) {
        Extensions3DChromium* parentExt = static_cast<Extensions3DChromium*>(m_context->getExtensions());
        // For each child context:
        //   glSetLatch(Compositor->Offscreen);
        ChildContextMap::iterator i = m_childContexts.begin();
        for (; i != m_childContexts.end(); ++i) {
            Extensions3DChromium* childExt = static_cast<Extensions3DChromium*>(i->first->getExtensions());
            GC3Duint latchId;
            childExt->getParentToChildLatchCHROMIUM(&latchId);
            parentExt->setLatchCHROMIUM(latchId);
        }
    }

    if (isCompositingOffscreen())
        copyOffscreenTextureToDisplay();
}
Example #10
0
void CCPluginLayerImpl::draw(LayerRendererChromium* layerRenderer)
{
    ASSERT(CCProxy::isImplThread());

    if (m_ioSurfaceChanged) {
        GraphicsContext3D* context = layerRenderer->context();
        Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context->getExtensions());
        ASSERT(extensions->supports("GL_CHROMIUM_iosurface"));
        ASSERT(extensions->supports("GL_ARB_texture_rectangle"));

        if (!m_ioSurfaceTextureId)
            m_ioSurfaceTextureId = context->createTexture();

        GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
        GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId));
        GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
        GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
        GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
        GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
        extensions->texImageIOSurface2DCHROMIUM(Extensions3D::TEXTURE_RECTANGLE_ARB,
                                                m_ioSurfaceWidth,
                                                m_ioSurfaceHeight,
                                                m_ioSurfaceId,
                                                0);
        // Do not check for error conditions. texImageIOSurface2DCHROMIUM is supposed to hold on to
        // the last good IOSurface if the new one is already closed. This is only a possibility
        // during live resizing of plugins. However, it seems that this is not sufficient to
        // completely guard against garbage being drawn. If this is found to be a significant issue,
        // it may be necessary to explicitly tell the embedder when to free the surfaces it has
        // allocated.
        m_ioSurfaceChanged = false;
    }

    if (m_ioSurfaceTextureId) {
        TexTransformPluginProgramBinding binding;
        if (m_flipped)
            binding.set(layerRenderer->pluginLayerTexRectProgramFlip());
        else
            binding.set(layerRenderer->pluginLayerTexRectProgram());

        GraphicsContext3D* context = layerRenderer->context();
        GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
        GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId));

        GLC(context, context->useProgram(binding.programId));
        GLC(context, context->uniform1i(binding.samplerLocation, 0));
        // Note: this code path ignores m_uvRect.
        GLC(context, context->uniform4f(binding.texTransformLocation, 0, 0, m_ioSurfaceWidth, m_ioSurfaceHeight));
        layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(),
                                        binding.matrixLocation,
                                        binding.alphaLocation,
                                        -1);
        GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0));
    } else {
        TexStretchPluginProgramBinding binding;
        if (m_flipped)
            binding.set(layerRenderer->pluginLayerProgramFlip());
        else
            binding.set(layerRenderer->pluginLayerProgram());

        GraphicsContext3D* context = layerRenderer->context();
        GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
        GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId));

        // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
        // where it will only happen once per texture.
        GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
        GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
        GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
        GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));

        GLC(context, context->useProgram(binding.programId));
        GLC(context, context->uniform1i(binding.samplerLocation, 0));
        GLC(context, context->uniform2f(binding.offsetLocation, m_uvRect.x(), m_uvRect.y()));
        GLC(context, context->uniform2f(binding.scaleLocation, m_uvRect.width(), m_uvRect.height()));
        layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(),
                                        binding.matrixLocation,
                                        binding.alphaLocation,
                                        -1);
    }
}