示例#1
0
void VideoLayerChromium::drawYUV(const SharedValues* sv)
{
    GraphicsContext3D* context = layerRendererContext();
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::yPlane]));
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::uPlane]));
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::vPlane]));

    layerRenderer()->useShader(sv->yuvShaderProgram());
    unsigned frameWidth = m_frameSizes[VideoFrameChromium::yPlane].width();
    unsigned textureWidth = m_textureSizes[VideoFrameChromium::yPlane].width();
    float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth;
    GLC(context, context->uniform1f(sv->yuvWidthScaleFactorLocation(), widthScaleFactor));

    GLC(context, context->uniform1i(sv->yTextureLocation(), 1));
    GLC(context, context->uniform1i(sv->uTextureLocation(), 2));
    GLC(context, context->uniform1i(sv->vTextureLocation(), 3));

    GLC(context, context->uniformMatrix3fv(sv->ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1));

    drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
                     bounds().width(), bounds().height(), drawOpacity(),
                     sv->yuvShaderMatrixLocation(), sv->yuvAlphaLocation());

    // Reset active texture back to texture 0.
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
}
void ContentLayerChromium::draw()
{
    if (m_skipsDraw)
        return;

    ASSERT(layerRenderer());
    const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues();
    ASSERT(sv && sv->initialized());
    GraphicsContext3D* context = layerRendererContext();
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTexture));
    layerRenderer()->useShader(sv->contentShaderProgram());
    GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0));

    if (requiresClippedUpdateRect()) {
        float m43 = drawTransform().m43();
        TransformationMatrix transform;
        transform.translate3d(m_largeLayerDrawRect.center().x(), m_largeLayerDrawRect.center().y(), m43);
        drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
                         transform, m_largeLayerDrawRect.width(),
                         m_largeLayerDrawRect.height(), drawOpacity(),
                         sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
    } else {
        drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
                         drawTransform(), m_bounds.width(), m_bounds.height(),
                         drawOpacity(), sv->shaderMatrixLocation(),
                         sv->shaderAlphaLocation());
    }
}
示例#3
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;
    }
}
void Canvas2DLayerChromium::updateCompositorResources()
{
    if (!m_contentsDirty || !m_drawingBuffer)
        return;
    if (m_textureChanged) { // We have to generate a new backing texture.
        GraphicsContext3D* context = layerRendererContext();
        if (m_textureId)
            context->deleteTexture(m_textureId);
        m_textureId = context->createTexture();
        context->activeTexture(GraphicsContext3D::TEXTURE0);
        context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
        IntSize size = m_drawingBuffer->size();
        context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
        // Set the min-mag filters to linear and wrap modes to GraphicsContext3D::CLAMP_TO_EDGE
        // to get around NPOT texture limitations of GLES.
        context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
        context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
        context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
        context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
        m_textureChanged = false;
        // FIXME: The finish() here is required because we have to make sure that the texture created in this
        // context (the compositor context) is actually created by the service side before the child context
        // attempts to use it (in publishToPlatformLayer).  finish() is currently the only call with strong
        // enough semantics to promise this, but is actually much stronger.  Ideally we'd do something like
        // inserting a fence here and waiting for it before trying to publish.
        context->finish();
    }
    // Update the contents of the texture used by the compositor.
    if (m_contentsDirty) {
        m_drawingBuffer->publishToPlatformLayer();
        m_contentsDirty = false;
    }
}
示例#5
0
void CCVideoLayerImpl::drawYUV(LayerRendererChromium* layerRenderer) const
{
    const YUVProgram* program = layerRenderer->videoLayerYUVProgram();
    ASSERT(program && program->initialized());

    GraphicsContext3D* context = layerRenderer->context();
    CCVideoLayerImpl::Texture yTexture = m_textures[VideoFrameChromium::yPlane];
    CCVideoLayerImpl::Texture uTexture = m_textures[VideoFrameChromium::uPlane];
    CCVideoLayerImpl::Texture vTexture = m_textures[VideoFrameChromium::vPlane];

    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.id));
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.id));
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.id));

    GLC(context, context->useProgram(program->program()));

    float yWidthScaleFactor = static_cast<float>(yTexture.visibleSize.width()) / yTexture.size.width();
    // Arbitrarily take the u sizes because u and v dimensions are identical.
    float uvWidthScaleFactor = static_cast<float>(uTexture.visibleSize.width()) / uTexture.size.width();
    GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
    GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));

    GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1));
    GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2));
    GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3));

    GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1));
    GLC(context, context->uniform3fv(program->fragmentShader().yuvAdjLocation(), const_cast<float*>(yuvAdjust), 1));

    layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), FloatQuad(),
                                    program->vertexShader().matrixLocation(),
                                    program->fragmentShader().alphaLocation(),
                                    -1);

    // Reset active texture back to texture 0.
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
}
示例#6
0
void ContentLayerChromium::draw()
{
    if (m_skipsDraw)
        return;

    ASSERT(layerRenderer());
    const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues();
    ASSERT(sv && sv->initialized());
    GraphicsContext3D* context = layerRendererContext();
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTexture));
    layerRenderer()->useShader(sv->contentShaderProgram());
    GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0));
    drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
                     bounds().width(), bounds().height(), drawOpacity(),
                     sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
}
示例#7
0
void VideoLayerChromium::drawRGBA(const SharedValues* sv)
{
    GraphicsContext3D* context = layerRendererContext();
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::rgbPlane]));

    layerRenderer()->useShader(sv->rgbaShaderProgram());
    unsigned frameWidth = m_frameSizes[VideoFrameChromium::rgbPlane].width();
    unsigned textureWidth = m_textureSizes[VideoFrameChromium::rgbPlane].width();
    float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth;
    GLC(context, context->uniform1f(sv->rgbaWidthScaleFactorLocation(), widthScaleFactor));

    GLC(context, context->uniform1i(sv->rgbaTextureLocation(), 0));

    drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
                     bounds().width(), bounds().height(), drawOpacity(),
                     sv->rgbaShaderMatrixLocation(), sv->rgbaAlphaLocation());
}
void CCCanvasLayerImpl::draw(const IntRect&)
{
    ASSERT(layerRenderer());
    const CCCanvasLayerImpl::Program* program = layerRenderer()->canvasLayerProgram();
    ASSERT(program && program->initialized());
    GraphicsContext3D* context = layerRenderer()->context();
    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId));
    GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA;
    GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
    layerRenderer()->useShader(program->program());
    GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
    LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
                                    bounds().width(), bounds().height(), drawOpacity(),
                                    program->vertexShader().matrixLocation(),
                                    program->fragmentShader().alphaLocation());

}
示例#9
0
void CCVideoLayerImpl::drawNativeTexture(LayerRendererChromium* layerRenderer) const
{
    const NativeTextureProgram* program = layerRenderer->videoLayerNativeTextureProgram();
    ASSERT(program && program->initialized());

    GraphicsContext3D* context = layerRenderer->context();

    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_nativeTextureId));

    GLC(context, context->useProgram(program->program()));
    float widthScaleFactor = static_cast<float>(m_nativeTextureVisibleSize.width()) / m_nativeTextureSize.width();
    GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1));

    GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));

    layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(),
                                    program->vertexShader().matrixLocation(),
                                    program->fragmentShader().alphaLocation(),
                                    -1);
}
void CCPluginLayerImpl::draw()
{
    ASSERT(layerRenderer());
    const CCPluginLayerImpl::Program* program = layerRenderer()->pluginLayerProgram();
    ASSERT(program && program->initialized());
    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));

    layerRenderer()->useShader(program->program());
    GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
    LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
                                    bounds().width(), bounds().height(), drawOpacity(),
                                    program->vertexShader().matrixLocation(),
                                    program->fragmentShader().alphaLocation());
}
示例#11
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();
}
示例#12
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);
    }
}