// Copyright 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"

#include "cc/gl_renderer.h"

#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/string_split.h"
#include "base/string_util.h"
#include "cc/damage_tracker.h"
#include "cc/geometry_binding.h"
#include "cc/layer_quad.h"
#include "cc/math_util.h"
#include "cc/platform_color.h"
#include "cc/priority_calculator.h"
#include "cc/proxy.h"
#include "cc/render_pass.h"
#include "cc/render_surface_filters.h"
#include "cc/scoped_resource.h"
#include "cc/settings.h"
#include "cc/single_thread_proxy.h"
#include "cc/stream_video_draw_quad.h"
#include "cc/texture_draw_quad.h"
#include "cc/video_layer_impl.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/GrTexture.h"
#include "third_party/skia/include/gpu/SkGpuDevice.h"
#include "third_party/skia/include/gpu/SkGrTexturePixelRef.h"
#include "ui/gfx/quad_f.h"
#include "ui/gfx/rect_conversions.h"
#include <public/WebGraphicsContext3D.h>
#include <public/WebSharedGraphicsContext3D.h>
#include <set>
#include <string>
#include <vector>

using namespace std;
using WebKit::WebGraphicsContext3D;
using WebKit::WebGraphicsMemoryAllocation;
using WebKit::WebSharedGraphicsContext3D;
using WebKit::WebTransformationMatrix;

namespace cc {

namespace {

bool needsIOSurfaceReadbackWorkaround()
{
#if OS(DARWIN)
    return true;
#else
    return false;
#endif
}

} // anonymous namespace

scoped_ptr<GLRenderer> GLRenderer::create(RendererClient* client, ResourceProvider* resourceProvider)
{
    scoped_ptr<GLRenderer> renderer(make_scoped_ptr(new GLRenderer(client, resourceProvider)));
    if (!renderer->initialize())
        return scoped_ptr<GLRenderer>();

    return renderer.Pass();
}

GLRenderer::GLRenderer(RendererClient* client,
                           ResourceProvider* resourceProvider)
    : DirectRenderer(client, resourceProvider)
    , m_offscreenFramebufferId(0)
    , m_sharedGeometryQuad(gfx::RectF(-0.5f, -0.5f, 1.0f, 1.0f))
    , m_context(resourceProvider->graphicsContext3D())
    , m_isViewportChanged(false)
    , m_isFramebufferDiscarded(false)
    , m_discardFramebufferWhenNotVisible(false)
    , m_isUsingBindUniform(false)
    , m_visible(true)
{
    DCHECK(m_context);
}

bool GLRenderer::initialize()
{
    if (!m_context->makeContextCurrent())
        return false;

    m_context->setContextLostCallback(this);
    m_context->pushGroupMarkerEXT("CompositorContext");

    std::string extensionsString = UTF16ToASCII(m_context->getString(GL_EXTENSIONS));
    std::vector<std::string> extensionsList;
    base::SplitString(extensionsString, ' ', &extensionsList);
    std::set<string> extensions(extensionsList.begin(), extensionsList.end());

    if (settings().acceleratePainting && extensions.count("GL_EXT_texture_format_BGRA8888")
                                      && extensions.count("GL_EXT_read_format_bgra"))
        m_capabilities.usingAcceleratedPainting = true;
    else
        m_capabilities.usingAcceleratedPainting = false;


    m_capabilities.contextHasCachedFrontBuffer = extensions.count("GL_CHROMIUM_front_buffer_cached");

    m_capabilities.usingPartialSwap = Settings::partialSwapEnabled() && extensions.count("GL_CHROMIUM_post_sub_buffer");

    // Use the swapBuffers callback only with the threaded proxy.
    if (m_client->hasImplThread())
        m_capabilities.usingSwapCompleteCallback = extensions.count("GL_CHROMIUM_swapbuffers_complete_callback");
    if (m_capabilities.usingSwapCompleteCallback)
        m_context->setSwapBuffersCompleteCallbackCHROMIUM(this);

    m_capabilities.usingSetVisibility = extensions.count("GL_CHROMIUM_set_visibility");

    if (extensions.count("GL_CHROMIUM_iosurface"))
        DCHECK(extensions.count("GL_ARB_texture_rectangle"));

    m_capabilities.usingGpuMemoryManager = extensions.count("GL_CHROMIUM_gpu_memory_manager");
    if (m_capabilities.usingGpuMemoryManager)
        m_context->setMemoryAllocationChangedCallbackCHROMIUM(this);

    m_capabilities.usingDiscardFramebuffer = extensions.count("GL_CHROMIUM_discard_framebuffer");

    m_capabilities.usingEglImage = extensions.count("GL_OES_EGL_image_external");

    GLC(m_context, m_context->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize));
    m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context, extensions.count("GL_EXT_texture_format_BGRA8888"));

    m_isUsingBindUniform = extensions.count("GL_CHROMIUM_bind_uniform_location");

    if (!initializeSharedObjects())
        return false;

    // Make sure the viewport and context gets initialized, even if it is to zero.
    viewportChanged();
    return true;
}

GLRenderer::~GLRenderer()
{
    m_context->setSwapBuffersCompleteCallbackCHROMIUM(0);
    m_context->setMemoryAllocationChangedCallbackCHROMIUM(0);
    m_context->setContextLostCallback(0);
    cleanupSharedObjects();
}

const RendererCapabilities& GLRenderer::capabilities() const
{
    return m_capabilities;
}

WebGraphicsContext3D* GLRenderer::context()
{
    return m_context;
}

void GLRenderer::debugGLCall(WebGraphicsContext3D* context, const char* command, const char* file, int line)
{
    unsigned long error = context->getError();
    if (error != GL_NO_ERROR)
        LOG(ERROR) << "GL command failed: File: " << file << "\n\tLine " << line << "\n\tcommand: " << command << ", error " << static_cast<int>(error) << "\n";
}

void GLRenderer::setVisible(bool visible)
{
    if (m_visible == visible)
        return;
    m_visible = visible;

    enforceMemoryPolicy();

    // TODO: Replace setVisibilityCHROMIUM with an extension to explicitly manage front/backbuffers
    // crbug.com/116049
    if (m_capabilities.usingSetVisibility)
        m_context->setVisibilityCHROMIUM(visible);
}

void GLRenderer::sendManagedMemoryStats(size_t bytesVisible, size_t bytesVisibleAndNearby, size_t bytesAllocated)
{
    WebKit::WebGraphicsManagedMemoryStats stats;
    stats.bytesVisible = bytesVisible;
    stats.bytesVisibleAndNearby = bytesVisibleAndNearby;
    stats.bytesAllocated = bytesAllocated;
    stats.backbufferRequested = !m_isFramebufferDiscarded;
    m_context->sendManagedMemoryStatsCHROMIUM(&stats);
}

void GLRenderer::releaseRenderPassTextures()
{
    m_renderPassTextures.clear();
}

void GLRenderer::viewportChanged()
{
    m_isViewportChanged = true;
}

void GLRenderer::clearFramebuffer(DrawingFrame& frame)
{
    // On DEBUG builds, opaque render passes are cleared to blue to easily see regions that were not drawn on the screen.
    if (frame.currentRenderPass->hasTransparentBackground())
        GLC(m_context, m_context->clearColor(0, 0, 0, 0));
    else
        GLC(m_context, m_context->clearColor(0, 0, 1, 1));

#ifdef NDEBUG
    if (frame.currentRenderPass->hasTransparentBackground())
#endif
        m_context->clear(GL_COLOR_BUFFER_BIT);
}

void GLRenderer::beginDrawingFrame(DrawingFrame& frame)
{
    // FIXME: Remove this once framebuffer is automatically recreated on first use
    ensureFramebuffer();

    if (viewportSize().IsEmpty())
        return;

    TRACE_EVENT0("cc", "GLRenderer::drawLayers");
    if (m_isViewportChanged) {
        // Only reshape when we know we are going to draw. Otherwise, the reshape
        // can leave the window at the wrong size if we never draw and the proper
        // viewport size is never set.
        m_isViewportChanged = false;
        m_context->reshape(viewportWidth(), viewportHeight());
    }

    makeContextCurrent();
    // Bind the common vertex attributes used for drawing all the layers.
    m_sharedGeometry->prepareForDraw();

    GLC(m_context, m_context->disable(GL_DEPTH_TEST));
    GLC(m_context, m_context->disable(GL_CULL_FACE));
    GLC(m_context, m_context->enable(GL_SCISSOR_TEST));
    GLC(m_context, m_context->colorMask(true, true, true, true));
    GLC(m_context, m_context->enable(GL_BLEND));
    GLC(m_context, m_context->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
}

void GLRenderer::doNoOp()
{
    GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0));
    GLC(m_context, m_context->flush());
}

void GLRenderer::drawQuad(DrawingFrame& frame, const DrawQuad* quad)
{
    if (quad->needsBlending())
        GLC(m_context, m_context->enable(GL_BLEND));
    else
        GLC(m_context, m_context->disable(GL_BLEND));

    switch (quad->material()) {
    case DrawQuad::Invalid:
        NOTREACHED();
        break;
    case DrawQuad::Checkerboard:
        drawCheckerboardQuad(frame, CheckerboardDrawQuad::materialCast(quad));
        break;
    case DrawQuad::DebugBorder:
        drawDebugBorderQuad(frame, DebugBorderDrawQuad::materialCast(quad));
        break;
    case DrawQuad::IOSurfaceContent:
        drawIOSurfaceQuad(frame, IOSurfaceDrawQuad::materialCast(quad));
        break;
    case DrawQuad::RenderPass:
        drawRenderPassQuad(frame, RenderPassDrawQuad::materialCast(quad));
        break;
    case DrawQuad::SolidColor:
        drawSolidColorQuad(frame, SolidColorDrawQuad::materialCast(quad));
        break;
    case DrawQuad::StreamVideoContent:
        drawStreamVideoQuad(frame, StreamVideoDrawQuad::materialCast(quad));
        break;
    case DrawQuad::TextureContent:
        drawTextureQuad(frame, TextureDrawQuad::materialCast(quad));
        break;
    case DrawQuad::TiledContent:
        drawTileQuad(frame, TileDrawQuad::materialCast(quad));
        break;
    case DrawQuad::YUVVideoContent:
        drawYUVVideoQuad(frame, YUVVideoDrawQuad::materialCast(quad));
        break;
    }
}

void GLRenderer::drawCheckerboardQuad(const DrawingFrame& frame, const CheckerboardDrawQuad* quad)
{
    const TileCheckerboardProgram* program = tileCheckerboardProgram();
    DCHECK(program && program->initialized());
    GLC(context(), context()->useProgram(program->program()));

    SkColor color = quad->color();
    GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), SkColorGetR(color) / 255.0, SkColorGetG(color) / 255.0, SkColorGetB(color) / 255.0, 1));

    const int checkerboardWidth = 16;
    float frequency = 1.0 / checkerboardWidth;

    gfx::Rect tileRect = quad->quadRect();
    float texOffsetX = tileRect.x() % checkerboardWidth;
    float texOffsetY = tileRect.y() % checkerboardWidth;
    float texScaleX = tileRect.width();
    float texScaleY = tileRect.height();
    GLC(context(), context()->uniform4f(program->fragmentShader().texTransformLocation(), texOffsetX, texOffsetY, texScaleX, texScaleY));

    GLC(context(), context()->uniform1f(program->fragmentShader().frequencyLocation(), frequency));

    setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation());
    drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation());
}

void GLRenderer::drawDebugBorderQuad(const DrawingFrame& frame, const DebugBorderDrawQuad* quad)
{
    static float glMatrix[16];
    const SolidColorProgram* program = solidColorProgram();
    DCHECK(program && program->initialized());
    GLC(context(), context()->useProgram(program->program()));

    // Use the full quadRect for debug quads to not move the edges based on partial swaps.
    const gfx::Rect& layerRect = quad->quadRect();
    WebTransformationMatrix renderMatrix = quad->quadTransform();
    renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerRect.height() + layerRect.y());
    renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height());
    GLRenderer::toGLMatrix(&glMatrix[0], frame.projectionMatrix * renderMatrix);
    GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLocation(), 1, false, &glMatrix[0]));

    SkColor color = quad->color();
    float alpha = SkColorGetA(color) / 255.0;

    GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha));

    GLC(context(), context()->lineWidth(quad->width()));

    // The indices for the line are stored in the same array as the triangle indices.
    GLC(context(), context()->drawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
}

static WebGraphicsContext3D* getFilterContext(bool hasImplThread)
{
    if (hasImplThread)
        return WebSharedGraphicsContext3D::compositorThreadContext();
    else
        return WebSharedGraphicsContext3D::mainThreadContext();
}

static GrContext* getFilterGrContext(bool hasImplThread)
{
    if (hasImplThread)
        return WebSharedGraphicsContext3D::compositorThreadGrContext();
    else
        return WebSharedGraphicsContext3D::mainThreadGrContext();
}

static inline SkBitmap applyFilters(GLRenderer* renderer, const WebKit::WebFilterOperations& filters, ScopedResource* sourceTexture, bool hasImplThread)
{
    if (filters.isEmpty())
        return SkBitmap();

    WebGraphicsContext3D* filterContext = getFilterContext(hasImplThread);
    GrContext* filterGrContext = getFilterGrContext(hasImplThread);

    if (!filterContext || !filterGrContext)
        return SkBitmap();

    renderer->context()->flush();

    ResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTexture->id());
    SkBitmap source = RenderSurfaceFilters::apply(filters, lock.textureId(), sourceTexture->size(), filterContext, filterGrContext);
    return source;
}

static SkBitmap applyImageFilter(GLRenderer* renderer, SkImageFilter* filter, ScopedResource* sourceTexture, bool hasImplThread)
{
    if (!filter)
        return SkBitmap();

    WebGraphicsContext3D* context3d = getFilterContext(hasImplThread);
    GrContext* grContext = getFilterGrContext(hasImplThread);

    if (!context3d || !grContext)
        return SkBitmap();

    renderer->context()->flush();

    ResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTexture->id());

    // Wrap the source texture in a Ganesh platform texture.
    GrPlatformTextureDesc platformTextureDescription;
    platformTextureDescription.fWidth = sourceTexture->size().width();
    platformTextureDescription.fHeight = sourceTexture->size().height();
    platformTextureDescription.fConfig = kSkia8888_GrPixelConfig;
    platformTextureDescription.fTextureHandle = lock.textureId();
    SkAutoTUnref<GrTexture> texture(grContext->createPlatformTexture(platformTextureDescription));

    // Place the platform texture inside an SkBitmap.
    SkBitmap source;
    source.setConfig(SkBitmap::kARGB_8888_Config, sourceTexture->size().width(), sourceTexture->size().height());
    source.setPixelRef(new SkGrPixelRef(texture.get()))->unref();

    // Create a scratch texture for backing store.
    GrTextureDesc desc;
    desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
    desc.fSampleCnt = 0;
    desc.fWidth = source.width();
    desc.fHeight = source.height();
    desc.fConfig = kSkia8888_GrPixelConfig;
    GrAutoScratchTexture scratchTexture(grContext, desc, GrContext::kExact_ScratchTexMatch);
    SkAutoTUnref<GrTexture> backingStore(scratchTexture.detach());

    // Create a device and canvas using that backing store.
    SkGpuDevice device(grContext, backingStore.get());
    SkCanvas canvas(&device);

    // Draw the source bitmap through the filter to the canvas.
    SkPaint paint;
    paint.setImageFilter(filter);
    canvas.clear(0x0);
    canvas.drawSprite(source, 0, 0, &paint);
    canvas.flush();
    context3d->flush();
    return device.accessBitmap(false);
}

scoped_ptr<ScopedResource> GLRenderer::drawBackgroundFilters(
    DrawingFrame& frame, const RenderPassDrawQuad* quad,
    const WebKit::WebFilterOperations& filters,
    const WebTransformationMatrix& contentsDeviceTransform,
    const WebTransformationMatrix& contentsDeviceTransformInverse)
{
    // This method draws a background filter, which applies a filter to any pixels behind the quad and seen through its background.
    // The algorithm works as follows:
    // 1. Compute a bounding box around the pixels that will be visible through the quad.
    // 2. Read the pixels in the bounding box into a buffer R.
    // 3. Apply the background filter to R, so that it is applied in the pixels' coordinate space.
    // 4. Apply the quad's inverse transform to map the pixels in R into the quad's content space. This implicitly
    // clips R by the content bounds of the quad since the destination texture has bounds matching the quad's content.
    // 5. Draw the background texture for the contents using the same transform as used to draw the contents itself. This is done
    // without blending to replace the current background pixels with the new filtered background.
    // 6. Draw the contents of the quad over drop of the new background with blending, as per usual. The filtered background
    // pixels will show through any non-opaque pixels in this draws.
    //
    // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.

    // FIXME: When this algorithm changes, update LayerTreeHost::prioritizeTextures() accordingly.

    if (filters.isEmpty())
        return scoped_ptr<ScopedResource>();

    // FIXME: We only allow background filters on an opaque render surface because other surfaces may contain
    // translucent pixels, and the contents behind those translucent pixels wouldn't have the filter applied.
    if (frame.currentRenderPass->hasTransparentBackground())
        return scoped_ptr<ScopedResource>();
    DCHECK(!frame.currentTexture);

    // FIXME: Do a single readback for both the surface and replica and cache the filtered results (once filter textures are not reused).
    gfx::Rect deviceRect = gfx::ToEnclosingRect(MathUtil::mapClippedRect(contentsDeviceTransform, sharedGeometryQuad().BoundingBox()));

    int top, right, bottom, left;
    filters.getOutsets(top, right, bottom, left);
    deviceRect.Inset(-left, -top, -right, -bottom);

    deviceRect.Intersect(frame.currentRenderPass->outputRect());

    scoped_ptr<ScopedResource> deviceBackgroundTexture = ScopedResource::create(m_resourceProvider);
    if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect))
        return scoped_ptr<ScopedResource>();

    SkBitmap filteredDeviceBackground = applyFilters(this, filters, deviceBackgroundTexture.get(), m_client->hasImplThread());
    if (!filteredDeviceBackground.getTexture())
        return scoped_ptr<ScopedResource>();

    GrTexture* texture = reinterpret_cast<GrTexture*>(filteredDeviceBackground.getTexture());
    int filteredDeviceBackgroundTextureId = texture->getTextureHandle();

    scoped_ptr<ScopedResource> backgroundTexture = ScopedResource::create(m_resourceProvider);
    if (!backgroundTexture->allocate(Renderer::ImplPool, quad->quadRect().size(), GL_RGBA, ResourceProvider::TextureUsageFramebuffer))
        return scoped_ptr<ScopedResource>();

    const RenderPass* targetRenderPass = frame.currentRenderPass;
    bool usingBackgroundTexture = useScopedTexture(frame, backgroundTexture.get(), quad->quadRect());

    if (usingBackgroundTexture) {
        // Copy the readback pixels from device to the background texture for the surface.
        WebTransformationMatrix deviceToFramebufferTransform;
        deviceToFramebufferTransform.translate(quad->quadRect().width() / 2.0, quad->quadRect().height() / 2.0);
        deviceToFramebufferTransform.scale3d(quad->quadRect().width(), quad->quadRect().height(), 1);
        deviceToFramebufferTransform.multiply(contentsDeviceTransformInverse);
        copyTextureToFramebuffer(frame, filteredDeviceBackgroundTextureId, deviceRect, deviceToFramebufferTransform);
    }

    useRenderPass(frame, targetRenderPass);

    if (!usingBackgroundTexture)
        return scoped_ptr<ScopedResource>();
    return backgroundTexture.Pass();
}

void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQuad* quad)
{
    CachedResource* contentsTexture = m_renderPassTextures.get(quad->renderPassId());
    if (!contentsTexture || !contentsTexture->id())
        return;

    const RenderPass* renderPass = frame.renderPassesById->get(quad->renderPassId());
    DCHECK(renderPass);
    if (!renderPass)
        return;

    WebTransformationMatrix quadRectMatrix;
    quadRectTransform(&quadRectMatrix, quad->quadTransform(), quad->quadRect());
    WebTransformationMatrix contentsDeviceTransform = (frame.windowMatrix * frame.projectionMatrix * quadRectMatrix).to2dTransform();

    // Can only draw surface if device matrix is invertible.
    if (!contentsDeviceTransform.isInvertible())
        return;

    WebTransformationMatrix contentsDeviceTransformInverse = contentsDeviceTransform.inverse();
    scoped_ptr<ScopedResource> backgroundTexture = drawBackgroundFilters(
        frame, quad, renderPass->backgroundFilters(),
        contentsDeviceTransform, contentsDeviceTransformInverse);

    // FIXME: Cache this value so that we don't have to do it for both the surface and its replica.
    // Apply filters to the contents texture.
    SkBitmap filterBitmap;
    if (renderPass->filter()) {
        filterBitmap = applyImageFilter(this, renderPass->filter(), contentsTexture, m_client->hasImplThread());
    } else {
        filterBitmap = applyFilters(this, renderPass->filters(), contentsTexture, m_client->hasImplThread());
    }
    scoped_ptr<ResourceProvider::ScopedReadLockGL> contentsResourceLock;
    unsigned contentsTextureId = 0;
    if (filterBitmap.getTexture()) {
        GrTexture* texture = reinterpret_cast<GrTexture*>(filterBitmap.getTexture());
        contentsTextureId = texture->getTextureHandle();
    } else {
        contentsResourceLock = make_scoped_ptr(new ResourceProvider::ScopedReadLockGL(m_resourceProvider, contentsTexture->id()));
        contentsTextureId = contentsResourceLock->textureId();
    }

    // Draw the background texture if there is one.
    if (backgroundTexture) {
        DCHECK(backgroundTexture->size() == quad->quadRect().size());
        ResourceProvider::ScopedReadLockGL lock(m_resourceProvider, backgroundTexture->id());
        copyTextureToFramebuffer(frame, lock.textureId(), quad->quadRect(), quad->quadTransform());
    }

    bool clipped = false;
    gfx::QuadF deviceQuad = MathUtil::mapQuad(contentsDeviceTransform, sharedGeometryQuad(), clipped);
    DCHECK(!clipped);
    LayerQuad deviceLayerBounds = LayerQuad(gfx::QuadF(deviceQuad.BoundingBox()));
    LayerQuad deviceLayerEdges = LayerQuad(deviceQuad);

    // Use anti-aliasing programs only when necessary.
    bool useAA = (!deviceQuad.IsRectilinear() || !deviceQuad.BoundingBox().IsExpressibleAsRect());
    if (useAA) {
        deviceLayerBounds.inflateAntiAliasingDistance();
        deviceLayerEdges.inflateAntiAliasingDistance();
    }

    scoped_ptr<ResourceProvider::ScopedReadLockGL> maskResourceLock;
    unsigned maskTextureId = 0;
    if (quad->maskResourceId()) {
        maskResourceLock.reset(new ResourceProvider::ScopedReadLockGL(m_resourceProvider, quad->maskResourceId()));
        maskTextureId = maskResourceLock->textureId();
    }

    // FIXME: use the backgroundTexture and blend the background in with this draw instead of having a separate copy of the background texture.

    GLC(context(), context()->activeTexture(GL_TEXTURE0));
    context()->bindTexture(GL_TEXTURE_2D, contentsTextureId);

    int shaderQuadLocation = -1;
    int shaderEdgeLocation = -1;
    int shaderMaskSamplerLocation = -1;
    int shaderMaskTexCoordScaleLocation = -1;
    int shaderMaskTexCoordOffsetLocation = -1;
    int shaderMatrixLocation = -1;
    int shaderAlphaLocation = -1;
    if (useAA && maskTextureId) {
        const RenderPassMaskProgramAA* program = renderPassMaskProgramAA();
        GLC(context(), context()->useProgram(program->program()));
        GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));

        shaderQuadLocation = program->vertexShader().pointLocation();
        shaderEdgeLocation = program->fragmentShader().edgeLocation();
        shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation();
        shaderMaskTexCoordScaleLocation = program->fragmentShader().maskTexCoordScaleLocation();
        shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation();
        shaderMatrixLocation = program->vertexShader().matrixLocation();
        shaderAlphaLocation = program->fragmentShader().alphaLocation();
    } else if (!useAA && maskTextureId) {
        const RenderPassMaskProgram* program = renderPassMaskProgram();
        GLC(context(), context()->useProgram(program->program()));
        GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));

        shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation();
        shaderMaskTexCoordScaleLocation = program->fragmentShader().maskTexCoordScaleLocation();
        shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation();
        shaderMatrixLocation = program->vertexShader().matrixLocation();
        shaderAlphaLocation = program->fragmentShader().alphaLocation();
    } else if (useAA && !maskTextureId) {
        const RenderPassProgramAA* program = renderPassProgramAA();
        GLC(context(), context()->useProgram(program->program()));
        GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));

        shaderQuadLocation = program->vertexShader().pointLocation();
        shaderEdgeLocation = program->fragmentShader().edgeLocation();
        shaderMatrixLocation = program->vertexShader().matrixLocation();
        shaderAlphaLocation = program->fragmentShader().alphaLocation();
    } else {
        const RenderPassProgram* program = renderPassProgram();
        GLC(context(), context()->useProgram(program->program()));
        GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));

        shaderMatrixLocation = program->vertexShader().matrixLocation();
        shaderAlphaLocation = program->fragmentShader().alphaLocation();
    }

    if (shaderMaskSamplerLocation != -1) {
        DCHECK(shaderMaskTexCoordScaleLocation != 1);
        DCHECK(shaderMaskTexCoordOffsetLocation != 1);
        GLC(context(), context()->activeTexture(GL_TEXTURE1));
        GLC(context(), context()->uniform1i(shaderMaskSamplerLocation, 1));
        GLC(context(), context()->uniform2f(shaderMaskTexCoordScaleLocation, quad->maskTexCoordScaleX(), quad->maskTexCoordScaleY()));
        GLC(context(), context()->uniform2f(shaderMaskTexCoordOffsetLocation, quad->maskTexCoordOffsetX(), quad->maskTexCoordOffsetY()));
        context()->bindTexture(GL_TEXTURE_2D, maskTextureId);
        GLC(context(), context()->activeTexture(GL_TEXTURE0));
    }

    if (shaderEdgeLocation != -1) {
        float edge[24];
        deviceLayerEdges.toFloatArray(edge);
        deviceLayerBounds.toFloatArray(&edge[12]);
        GLC(context(), context()->uniform3fv(shaderEdgeLocation, 8, edge));
    }

    // Map device space quad to surface space. contentsDeviceTransform has no 3d component since it was generated with to2dTransform() so we don't need to project.
    gfx::QuadF surfaceQuad = MathUtil::mapQuad(contentsDeviceTransformInverse, deviceLayerEdges.ToQuadF(), clipped);
    DCHECK(!clipped);

    setShaderOpacity(quad->opacity(), shaderAlphaLocation);
    setShaderQuadF(surfaceQuad, shaderQuadLocation);
    drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), shaderMatrixLocation);

    // Flush the compositor context before the filter bitmap goes out of
    // scope, so the draw gets processed before the filter texture gets deleted.
    if (filterBitmap.getTexture())
        m_context->flush();
}

void GLRenderer::drawSolidColorQuad(const DrawingFrame& frame, const SolidColorDrawQuad* quad)
{
    const SolidColorProgram* program = solidColorProgram();
    GLC(context(), context()->useProgram(program->program()));

    SkColor color = quad->color();
    float opacity = quad->opacity();
    float alpha = (SkColorGetA(color) / 255.0) * opacity;

    GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha));

    drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation());
}

struct TileProgramUniforms {
    unsigned program;
    unsigned samplerLocation;
    unsigned vertexTexTransformLocation;
    unsigned fragmentTexTransformLocation;
    unsigned edgeLocation;
    unsigned matrixLocation;
    unsigned alphaLocation;
    unsigned pointLocation;
};

template<class T>
static void tileUniformLocation(T program, TileProgramUniforms& uniforms)
{
    uniforms.program = program->program();
    uniforms.vertexTexTransformLocation = program->vertexShader().vertexTexTransformLocation();
    uniforms.matrixLocation = program->vertexShader().matrixLocation();
    uniforms.pointLocation = program->vertexShader().pointLocation();

    uniforms.samplerLocation = program->fragmentShader().samplerLocation();
    uniforms.alphaLocation = program->fragmentShader().alphaLocation();
    uniforms.fragmentTexTransformLocation = program->fragmentShader().fragmentTexTransformLocation();
    uniforms.edgeLocation = program->fragmentShader().edgeLocation();
}

void GLRenderer::drawTileQuad(const DrawingFrame& frame, const TileDrawQuad* quad)
{
    gfx::Rect tileRect = quad->quadVisibleRect();

    gfx::RectF clampRect(tileRect);
    // Clamp texture coordinates to avoid sampling outside the layer
    // by deflating the tile region half a texel or half a texel
    // minus epsilon for one pixel layers. The resulting clamp region
    // is mapped to the unit square by the vertex shader and mapped
    // back to normalized texture coordinates by the fragment shader
    // after being clamped to 0-1 range.
    const float epsilon = 1 / 1024.0f;
    float clampX = min(0.5, clampRect.width() / 2.0 - epsilon);
    float clampY = min(0.5, clampRect.height() / 2.0 - epsilon);
    clampRect.Inset(clampX, clampY, clampX, clampY);

    gfx::Vector2dF textureOffset = quad->textureOffset() + clampRect.OffsetFromOrigin() - quad->quadRect().OffsetFromOrigin();

    // Map clamping rectangle to unit square.
    float vertexTexTranslateX = -clampRect.x() / clampRect.width();
    float vertexTexTranslateY = -clampRect.y() / clampRect.height();
    float vertexTexScaleX = tileRect.width() / clampRect.width();
    float vertexTexScaleY = tileRect.height() / clampRect.height();

    // Map to normalized texture coordinates.
    const gfx::Size& textureSize = quad->textureSize();
    float fragmentTexTranslateX = textureOffset.x() / textureSize.width();
    float fragmentTexTranslateY = textureOffset.y() / textureSize.height();
    float fragmentTexScaleX = clampRect.width() / textureSize.width();
    float fragmentTexScaleY = clampRect.height() / textureSize.height();


    gfx::QuadF localQuad;
    WebTransformationMatrix deviceTransform = WebTransformationMatrix(frame.windowMatrix * frame.projectionMatrix * quad->quadTransform()).to2dTransform();
    if (!deviceTransform.isInvertible())
        return;

    bool clipped = false;
    gfx::QuadF deviceLayerQuad = MathUtil::mapQuad(deviceTransform, gfx::QuadF(quad->visibleContentRect()), clipped);
    DCHECK(!clipped);

    TileProgramUniforms uniforms;
    // For now, we simply skip anti-aliasing with the quad is clipped. This only happens
    // on perspective transformed layers that go partially behind the camera.
    if (quad->isAntialiased() && !clipped) {
        if (quad->swizzleContents())
            tileUniformLocation(tileProgramSwizzleAA(), uniforms);
        else
            tileUniformLocation(tileProgramAA(), uniforms);
    } else {
        if (quad->needsBlending()) {
            if (quad->swizzleContents())
                tileUniformLocation(tileProgramSwizzle(), uniforms);
            else
                tileUniformLocation(tileProgram(), uniforms);
        } else {
            if (quad->swizzleContents())
                tileUniformLocation(tileProgramSwizzleOpaque(), uniforms);
            else
                tileUniformLocation(tileProgramOpaque(), uniforms);
        }
    }

    GLC(context(), context()->useProgram(uniforms.program));
    GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0));
    GLC(context(), context()->activeTexture(GL_TEXTURE0));
    ResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId());
    GLC(context(), context()->bindTexture(GL_TEXTURE_2D, quadResourceLock.textureId()));
    GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, quad->textureFilter()));
    GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, quad->textureFilter()));

    bool useAA = !clipped && quad->isAntialiased();
    if (useAA) {
        LayerQuad deviceLayerBounds = LayerQuad(gfx::QuadF(deviceLayerQuad.BoundingBox()));
        deviceLayerBounds.inflateAntiAliasingDistance();

        LayerQuad deviceLayerEdges = LayerQuad(deviceLayerQuad);
        deviceLayerEdges.inflateAntiAliasingDistance();

        float edge[24];
        deviceLayerEdges.toFloatArray(edge);
        deviceLayerBounds.toFloatArray(&edge[12]);
        GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge));

        GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
        GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY));

        gfx::PointF bottomRight(tileRect.right(), tileRect.bottom());
        gfx::PointF bottomLeft(tileRect.x(), tileRect.bottom());
        gfx::PointF topLeft(tileRect.x(), tileRect.y());
        gfx::PointF topRight(tileRect.right(), tileRect.y());

        // Map points to device space.
        bottomRight = MathUtil::mapPoint(deviceTransform, bottomRight, clipped);
        DCHECK(!clipped);
        bottomLeft = MathUtil::mapPoint(deviceTransform, bottomLeft, clipped);
        DCHECK(!clipped);
        topLeft = MathUtil::mapPoint(deviceTransform, topLeft, clipped);
        DCHECK(!clipped);
        topRight = MathUtil::mapPoint(deviceTransform, topRight, clipped);
        DCHECK(!clipped);

        LayerQuad::Edge bottomEdge(bottomRight, bottomLeft);
        LayerQuad::Edge leftEdge(bottomLeft, topLeft);
        LayerQuad::Edge topEdge(topLeft, topRight);
        LayerQuad::Edge rightEdge(topRight, bottomRight);

        // Only apply anti-aliasing to edges not clipped by culling or scissoring.
        if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y())
            topEdge = deviceLayerEdges.top();
        if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x())
            leftEdge = deviceLayerEdges.left();
        if (quad->rightEdgeAA() && tileRect.right() == quad->quadRect().right())
            rightEdge = deviceLayerEdges.right();
        if (quad->bottomEdgeAA() && tileRect.bottom() == quad->quadRect().bottom())
            bottomEdge = deviceLayerEdges.bottom();

        float sign = gfx::QuadF(tileRect).IsCounterClockwise() ? -1 : 1;
        bottomEdge.scale(sign);
        leftEdge.scale(sign);
        topEdge.scale(sign);
        rightEdge.scale(sign);

        // Create device space quad.
        LayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);

        // Map device space quad to local space. deviceTransform has no 3d component since it was generated with to2dTransform() so we don't need to project.
        WebTransformationMatrix deviceTransformInverse = deviceTransform.inverse();
        localQuad = MathUtil::mapQuad(deviceTransformInverse, deviceQuad.ToQuadF(), clipped);

        // We should not DCHECK(!clipped) here, because anti-aliasing inflation may cause deviceQuad to become
        // clipped. To our knowledge this scenario does not need to be handled differently than the unclipped case.
    } else {
        // Move fragment shader transform to vertex shader. We can do this while
        // still producing correct results as fragmentTexTransformLocation
        // should always be non-negative when tiles are transformed in a way
        // that could result in sampling outside the layer.
        vertexTexScaleX *= fragmentTexScaleX;
        vertexTexScaleY *= fragmentTexScaleY;
        vertexTexTranslateX *= fragmentTexScaleX;
        vertexTexTranslateY *= fragmentTexScaleY;
        vertexTexTranslateX += fragmentTexTranslateX;
        vertexTexTranslateY += fragmentTexTranslateY;

        GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));

        localQuad = gfx::RectF(tileRect);
    }

    // Normalize to tileRect.
    localQuad.Scale(1.0f / tileRect.width(), 1.0f / tileRect.height());

    setShaderOpacity(quad->opacity(), uniforms.alphaLocation);
    setShaderQuadF(localQuad, uniforms.pointLocation);

    // The tile quad shader behaves differently compared to all other shaders.
    // The transform and vertex data are used to figure out the extents that the
    // un-antialiased quad should have and which vertex this is and the float
    // quad passed in via uniform is the actual geometry that gets used to draw
    // it. This is why this centered rect is used and not the original quadRect.
    gfx::RectF centeredRect(gfx::PointF(-0.5 * tileRect.width(), -0.5 * tileRect.height()), tileRect.size());
    drawQuadGeometry(frame, quad->quadTransform(), centeredRect, uniforms.matrixLocation);
}

void GLRenderer::drawYUVVideoQuad(const DrawingFrame& frame, const YUVVideoDrawQuad* quad)
{
    const VideoYUVProgram* program = videoYUVProgram();
    DCHECK(program && program->initialized());

    const VideoLayerImpl::FramePlane& yPlane = quad->yPlane();
    const VideoLayerImpl::FramePlane& uPlane = quad->uPlane();
    const VideoLayerImpl::FramePlane& vPlane = quad->vPlane();

    ResourceProvider::ScopedReadLockGL yPlaneLock(m_resourceProvider, yPlane.resourceId);
    ResourceProvider::ScopedReadLockGL uPlaneLock(m_resourceProvider, uPlane.resourceId);
    ResourceProvider::ScopedReadLockGL vPlaneLock(m_resourceProvider, vPlane.resourceId);
    GLC(context(), context()->activeTexture(GL_TEXTURE1));
    GLC(context(), context()->bindTexture(GL_TEXTURE_2D, yPlaneLock.textureId()));
    GLC(context(), context()->activeTexture(GL_TEXTURE2));
    GLC(context(), context()->bindTexture(GL_TEXTURE_2D, uPlaneLock.textureId()));
    GLC(context(), context()->activeTexture(GL_TEXTURE3));
    GLC(context(), context()->bindTexture(GL_TEXTURE_2D, vPlaneLock.textureId()));

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

    float yWidthScaleFactor = static_cast<float>(yPlane.visibleSize.width()) / yPlane.size.width();
    // Arbitrarily take the u sizes because u and v dimensions are identical.
    float uvWidthScaleFactor = static_cast<float>(uPlane.visibleSize.width()) / uPlane.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));

    // These values are magic numbers that are used in the transformation from YUV to RGB color values.
    // They are taken from the following webpage: http://www.fourcc.org/fccyvrgb.php
    float yuv2RGB[9] = {
        1.164f, 1.164f, 1.164f,
        0.f, -.391f, 2.018f,
        1.596f, -.813f, 0.f,
    };
    GLC(context(), context()->uniformMatrix3fv(program->fragmentShader().yuvMatrixLocation(), 1, 0, yuv2RGB));

    // These values map to 16, 128, and 128 respectively, and are computed
    // as a fraction over 256 (e.g. 16 / 256 = 0.0625).
    // They are used in the YUV to RGBA conversion formula:
    //   Y - 16   : Gives 16 values of head and footroom for overshooting
    //   U - 128  : Turns unsigned U into signed U [-128,127]
    //   V - 128  : Turns unsigned V into signed V [-128,127]
    float yuvAdjust[3] = {
        -0.0625f,
        -0.5f,
        -0.5f,
    };
    GLC(context(), context()->uniform3fv(program->fragmentShader().yuvAdjLocation(), 1, yuvAdjust));

    setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation());
    drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation());

    // Reset active texture back to texture 0.
    GLC(context(), context()->activeTexture(GL_TEXTURE0));
}

void GLRenderer::drawStreamVideoQuad(const DrawingFrame& frame, const StreamVideoDrawQuad* quad)
{
    static float glMatrix[16];

    DCHECK(m_capabilities.usingEglImage);

    const VideoStreamTextureProgram* program = videoStreamTextureProgram();
    GLC(context(), context()->useProgram(program->program()));

    toGLMatrix(&glMatrix[0], quad->matrix());
    GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrixLocation(), 1, false, glMatrix));

    GLC(context(), context()->activeTexture(GL_TEXTURE0));
    GLC(context(), context()->bindTexture(GL_TEXTURE_EXTERNAL_OES, quad->textureId()));

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

    setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation());
    drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation());
}

struct TextureProgramBinding {
    template<class Program> void set(Program* program)
    {
        DCHECK(program && program->initialized());
        programId = program->program();
        samplerLocation = program->fragmentShader().samplerLocation();
        matrixLocation = program->vertexShader().matrixLocation();
        alphaLocation = program->fragmentShader().alphaLocation();
    }
    int programId;
    int samplerLocation;
    int matrixLocation;
    int alphaLocation;
};

struct TexTransformTextureProgramBinding : TextureProgramBinding {
    template<class Program> void set(Program* program)
    {
        TextureProgramBinding::set(program);
        texTransformLocation = program->vertexShader().texTransformLocation();
    }
    int texTransformLocation;
};

void GLRenderer::drawTextureQuad(const DrawingFrame& frame, const TextureDrawQuad* quad)
{
    TexTransformTextureProgramBinding binding;
    if (quad->flipped())
        binding.set(textureProgramFlip());
    else
        binding.set(textureProgram());
    GLC(context(), context()->useProgram(binding.programId));
    GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
    const gfx::RectF& uvRect = quad->uvRect();
    GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height()));

    GLC(context(), context()->activeTexture(GL_TEXTURE0));
    ResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId());
    GLC(context(), context()->bindTexture(GL_TEXTURE_2D, quadResourceLock.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(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
    GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
    GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));

    if (!quad->premultipliedAlpha()) {
        // As it turns out, the premultiplied alpha blending function (ONE, ONE_MINUS_SRC_ALPHA)
        // will never cause the alpha channel to be set to anything less than 1.0 if it is
        // initialized to that value! Therefore, premultipliedAlpha being false is the first
        // situation we can generally see an alpha channel less than 1.0 coming out of the
        // compositor. This is causing platform differences in some layout tests (see
        // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use a separate
        // blend function for the alpha channel to avoid modifying it. Don't use colorMask for this
        // as it has performance implications on some platforms.
        GLC(context(), context()->blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE));
    }

    setShaderOpacity(quad->opacity(), binding.alphaLocation);
    drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.matrixLocation);

    if (!quad->premultipliedAlpha())
        GLC(m_context, m_context->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
}

void GLRenderer::drawIOSurfaceQuad(const DrawingFrame& frame, const IOSurfaceDrawQuad* quad)
{
    TexTransformTextureProgramBinding binding;
    binding.set(textureIOSurfaceProgram());

    GLC(context(), context()->useProgram(binding.programId));
    GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
    if (quad->orientation() == IOSurfaceDrawQuad::Flipped)
        GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, quad->ioSurfaceSize().height(), quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height() * -1.0));
    else
        GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height()));

    GLC(context(), context()->activeTexture(GL_TEXTURE0));
    GLC(context(), context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId()));

    setShaderOpacity(quad->opacity(), binding.alphaLocation);
    drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.matrixLocation);

    GLC(context(), context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB, 0));
}

void GLRenderer::finishDrawingFrame(DrawingFrame& frame)
{
    m_currentFramebufferLock.reset();
    m_swapBufferRect.Union(gfx::ToEnclosingRect(frame.rootDamageRect));

    GLC(m_context, m_context->disable(GL_BLEND));
}

bool GLRenderer::flippedFramebuffer() const
{
    return true;
}

void GLRenderer::toGLMatrix(float* flattened, const WebTransformationMatrix& m)
{
    flattened[0] = m.m11();
    flattened[1] = m.m12();
    flattened[2] = m.m13();
    flattened[3] = m.m14();
    flattened[4] = m.m21();
    flattened[5] = m.m22();
    flattened[6] = m.m23();
    flattened[7] = m.m24();
    flattened[8] = m.m31();
    flattened[9] = m.m32();
    flattened[10] = m.m33();
    flattened[11] = m.m34();
    flattened[12] = m.m41();
    flattened[13] = m.m42();
    flattened[14] = m.m43();
    flattened[15] = m.m44();
}

void GLRenderer::setShaderQuadF(const gfx::QuadF& quad, int quadLocation)
{
    if (quadLocation == -1)
        return;

    float point[8];
    point[0] = quad.p1().x();
    point[1] = quad.p1().y();
    point[2] = quad.p2().x();
    point[3] = quad.p2().y();
    point[4] = quad.p3().x();
    point[5] = quad.p3().y();
    point[6] = quad.p4().x();
    point[7] = quad.p4().y();
    GLC(m_context, m_context->uniform2fv(quadLocation, 4, point));
}

void GLRenderer::setShaderOpacity(float opacity, int alphaLocation)
{
    if (alphaLocation != -1)
        GLC(m_context, m_context->uniform1f(alphaLocation, opacity));
}

void GLRenderer::drawQuadGeometry(const DrawingFrame& frame, const WebKit::WebTransformationMatrix& drawTransform, const gfx::RectF& quadRect, int matrixLocation)
{
    WebTransformationMatrix quadRectMatrix;
    quadRectTransform(&quadRectMatrix, drawTransform, quadRect);
    static float glMatrix[16];
    toGLMatrix(&glMatrix[0], frame.projectionMatrix * quadRectMatrix);
    GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0]));

    GLC(m_context, m_context->drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0));
}

void GLRenderer::copyTextureToFramebuffer(const DrawingFrame& frame, int textureId, const gfx::Rect& rect, const WebTransformationMatrix& drawMatrix)
{
    const RenderPassProgram* program = renderPassProgram();

    GLC(context(), context()->activeTexture(GL_TEXTURE0));
    GLC(context(), context()->bindTexture(GL_TEXTURE_2D, textureId));
    GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
    GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
    GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
    GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));

    GLC(context(), context()->useProgram(program->program()));
    GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
    setShaderOpacity(1, program->fragmentShader().alphaLocation());
    drawQuadGeometry(frame, drawMatrix, rect, program->vertexShader().matrixLocation());
}

void GLRenderer::finish()
{
    TRACE_EVENT0("cc", "GLRenderer::finish");
    m_context->finish();
}

bool GLRenderer::swapBuffers()
{
    DCHECK(m_visible);
    DCHECK(!m_isFramebufferDiscarded);

    TRACE_EVENT0("cc", "GLRenderer::swapBuffers");
    // We're done! Time to swapbuffers!

    if (m_capabilities.usingPartialSwap) {
        // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport)
        m_swapBufferRect.Intersect(gfx::Rect(gfx::Point(), viewportSize()));
        int flippedYPosOfRectBottom = viewportHeight() - m_swapBufferRect.y() - m_swapBufferRect.height();
        m_context->postSubBufferCHROMIUM(m_swapBufferRect.x(), flippedYPosOfRectBottom, m_swapBufferRect.width(), m_swapBufferRect.height());
    } else {
        // Note that currently this has the same effect as swapBuffers; we should
        // consider exposing a different entry point on WebGraphicsContext3D.
        m_context->prepareTexture();
    }

    m_swapBufferRect = gfx::Rect();

    return true;
}

void GLRenderer::onSwapBuffersComplete()
{
    m_client->onSwapBuffersComplete();
}

void GLRenderer::onMemoryAllocationChanged(WebGraphicsMemoryAllocation allocation)
{
    // Just ignore the memory manager when it says to set the limit to zero
    // bytes. This will happen when the memory manager thinks that the renderer
    // is not visible (which the renderer knows better).
    if (allocation.bytesLimitWhenVisible) {
        ManagedMemoryPolicy policy(
            allocation.bytesLimitWhenVisible,
            priorityCutoffValue(allocation.priorityCutoffWhenVisible),
            allocation.bytesLimitWhenNotVisible,
            priorityCutoffValue(allocation.priorityCutoffWhenNotVisible));

        if (allocation.enforceButDoNotKeepAsPolicy)
            m_client->enforceManagedMemoryPolicy(policy);
        else
            m_client->setManagedMemoryPolicy(policy);
    }

    bool oldDiscardFramebufferWhenNotVisible = m_discardFramebufferWhenNotVisible;
    m_discardFramebufferWhenNotVisible = !allocation.suggestHaveBackbuffer;
    enforceMemoryPolicy();
    if (allocation.enforceButDoNotKeepAsPolicy)
        m_discardFramebufferWhenNotVisible = oldDiscardFramebufferWhenNotVisible;
}

int GLRenderer::priorityCutoffValue(WebKit::WebGraphicsMemoryAllocation::PriorityCutoff priorityCutoff)
{
    switch (priorityCutoff) {
    case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowNothing:
        return PriorityCalculator::allowNothingCutoff();
    case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleOnly:
        return PriorityCalculator::allowVisibleOnlyCutoff();
    case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleAndNearby:
        return PriorityCalculator::allowVisibleAndNearbyCutoff();
    case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowEverything:
        return PriorityCalculator::allowEverythingCutoff();
    }
    NOTREACHED();
    return 0;
}

void GLRenderer::enforceMemoryPolicy()
{
    if (!m_visible) {
        TRACE_EVENT0("cc", "GLRenderer::enforceMemoryPolicy dropping resources");
        releaseRenderPassTextures();
        if (m_discardFramebufferWhenNotVisible)
            discardFramebuffer();
        GLC(m_context, m_context->flush());
    }
}

void GLRenderer::discardFramebuffer()
{
    if (m_isFramebufferDiscarded)
        return;

    if (!m_capabilities.usingDiscardFramebuffer)
        return;

    // FIXME: Update attachments argument to appropriate values once they are no longer ignored.
    m_context->discardFramebufferEXT(GL_TEXTURE_2D, 0, 0);
    m_isFramebufferDiscarded = true;

    // Damage tracker needs a full reset every time framebuffer is discarded.
    m_client->setFullRootLayerDamage();
}

void GLRenderer::ensureFramebuffer()
{
    if (!m_isFramebufferDiscarded)
        return;

    if (!m_capabilities.usingDiscardFramebuffer)
        return;

    m_context->ensureFramebufferCHROMIUM();
    m_isFramebufferDiscarded = false;
}

void GLRenderer::onContextLost()
{
    m_client->didLoseContext();
}


void GLRenderer::getFramebufferPixels(void *pixels, const gfx::Rect& rect)
{
    DCHECK(rect.right() <= viewportWidth());
    DCHECK(rect.bottom() <= viewportHeight());

    if (!pixels)
        return;

    makeContextCurrent();

    bool doWorkaround = needsIOSurfaceReadbackWorkaround();

    GLuint temporaryTexture = 0;
    GLuint temporaryFBO = 0;

    if (doWorkaround) {
        // On Mac OS X, calling glReadPixels against an FBO whose color attachment is an
        // IOSurface-backed texture causes corruption of future glReadPixels calls, even those on
        // different OpenGL contexts. It is believed that this is the root cause of top crasher
        // http://crbug.com/99393. <rdar://problem/10949687>

        temporaryTexture = m_context->createTexture();
        GLC(m_context, m_context->bindTexture(GL_TEXTURE_2D, temporaryTexture));
        GLC(m_context, m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
        GLC(m_context, m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
        GLC(m_context, m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
        GLC(m_context, m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
        // Copy the contents of the current (IOSurface-backed) framebuffer into a temporary texture.
        GLC(m_context, m_context->copyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, viewportSize().width(), viewportSize().height(), 0));
        temporaryFBO = m_context->createFramebuffer();
        // Attach this texture to an FBO, and perform the readback from that FBO.
        GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, temporaryFBO));
        GLC(m_context, m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temporaryTexture, 0));

        DCHECK(m_context->checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
    }

    scoped_array<uint8_t> srcPixels(new uint8_t[rect.width() * rect.height() * 4]);
    GLC(m_context, m_context->readPixels(rect.x(), viewportSize().height() - rect.bottom(), rect.width(), rect.height(),
                                         GL_RGBA, GL_UNSIGNED_BYTE, srcPixels.get()));

    uint8_t* destPixels = static_cast<uint8_t*>(pixels);
    size_t rowBytes = rect.width() * 4;
    int numRows = rect.height();
    size_t totalBytes = numRows * rowBytes;
    for (size_t destY = 0; destY < totalBytes; destY += rowBytes) {
        // Flip Y axis.
        size_t srcY = totalBytes - destY - rowBytes;
        // Swizzle BGRA -> RGBA.
        for (size_t x = 0; x < rowBytes; x += 4) {
            destPixels[destY + (x+0)] = srcPixels.get()[srcY + (x+2)];
            destPixels[destY + (x+1)] = srcPixels.get()[srcY + (x+1)];
            destPixels[destY + (x+2)] = srcPixels.get()[srcY + (x+0)];
            destPixels[destY + (x+3)] = srcPixels.get()[srcY + (x+3)];
        }
    }

    if (doWorkaround) {
        // Clean up.
        GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0));
        GLC(m_context, m_context->bindTexture(GL_TEXTURE_2D, 0));
        GLC(m_context, m_context->deleteFramebuffer(temporaryFBO));
        GLC(m_context, m_context->deleteTexture(temporaryTexture));
    }

    enforceMemoryPolicy();
}

bool GLRenderer::getFramebufferTexture(ScopedResource* texture, const gfx::Rect& deviceRect)
{
    DCHECK(!texture->id() || (texture->size() == deviceRect.size() && texture->format() == GL_RGB));

    if (!texture->id() && !texture->allocate(Renderer::ImplPool, deviceRect.size(), GL_RGB, ResourceProvider::TextureUsageAny))
        return false;

    ResourceProvider::ScopedWriteLockGL lock(m_resourceProvider, texture->id());
    GLC(m_context, m_context->bindTexture(GL_TEXTURE_2D, lock.textureId()));
    GLC(m_context, m_context->copyTexImage2D(GL_TEXTURE_2D, 0, texture->format(),
                                             deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0));
    return true;
}

bool GLRenderer::useScopedTexture(DrawingFrame& frame, const ScopedResource* texture, const gfx::Rect& viewportRect)
{
    DCHECK(texture->id());
    frame.currentRenderPass = 0;
    frame.currentTexture = texture;

    return bindFramebufferToTexture(frame, texture, viewportRect);
}

void GLRenderer::bindFramebufferToOutputSurface(DrawingFrame& frame)
{
    m_currentFramebufferLock.reset();
    GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0));
}

bool GLRenderer::bindFramebufferToTexture(DrawingFrame& frame, const ScopedResource* texture, const gfx::Rect& framebufferRect)
{
    DCHECK(texture->id());

    GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, m_offscreenFramebufferId));
    m_currentFramebufferLock = make_scoped_ptr(new ResourceProvider::ScopedWriteLockGL(m_resourceProvider, texture->id()));
    unsigned textureId = m_currentFramebufferLock->textureId();
    GLC(m_context, m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));

    DCHECK(m_context->checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

    initializeMatrices(frame, framebufferRect, false);
    setDrawViewportSize(framebufferRect.size());

    return true;
}

void GLRenderer::setScissorTestRect(const gfx::Rect& scissorRect)
{
    GLC(m_context, m_context->scissor(scissorRect.x(), scissorRect.y(), scissorRect.width(), scissorRect.height()));
}

void GLRenderer::setDrawViewportSize(const gfx::Size& viewportSize)
{
    GLC(m_context, m_context->viewport(0, 0, viewportSize.width(), viewportSize.height()));
}

bool GLRenderer::makeContextCurrent()
{
    return m_context->makeContextCurrent();
}

bool GLRenderer::initializeSharedObjects()
{
    TRACE_EVENT0("cc", "GLRenderer::initializeSharedObjects");
    makeContextCurrent();

    // Create an FBO for doing offscreen rendering.
    GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer());

    // We will always need these programs to render, so create the programs eagerly so that the shader compilation can
    // start while we do other work. Other programs are created lazily on first access.
    m_sharedGeometry = make_scoped_ptr(new GeometryBinding(m_context, quadVertexRect()));
    m_renderPassProgram = make_scoped_ptr(new RenderPassProgram(m_context));
    m_tileProgram = make_scoped_ptr(new TileProgram(m_context));
    m_tileProgramOpaque = make_scoped_ptr(new TileProgramOpaque(m_context));

    GLC(m_context, m_context->flush());

    return true;
}

const GLRenderer::TileCheckerboardProgram* GLRenderer::tileCheckerboardProgram()
{
    if (!m_tileCheckerboardProgram)
        m_tileCheckerboardProgram = make_scoped_ptr(new TileCheckerboardProgram(m_context));
    if (!m_tileCheckerboardProgram->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::checkerboardProgram::initalize");
        m_tileCheckerboardProgram->initialize(m_context, m_isUsingBindUniform);
    }
    return m_tileCheckerboardProgram.get();
}

const GLRenderer::SolidColorProgram* GLRenderer::solidColorProgram()
{
    if (!m_solidColorProgram)
        m_solidColorProgram = make_scoped_ptr(new SolidColorProgram(m_context));
    if (!m_solidColorProgram->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::solidColorProgram::initialize");
        m_solidColorProgram->initialize(m_context, m_isUsingBindUniform);
    }
    return m_solidColorProgram.get();
}

const GLRenderer::RenderPassProgram* GLRenderer::renderPassProgram()
{
    DCHECK(m_renderPassProgram);
    if (!m_renderPassProgram->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::renderPassProgram::initialize");
        m_renderPassProgram->initialize(m_context, m_isUsingBindUniform);
    }
    return m_renderPassProgram.get();
}

const GLRenderer::RenderPassProgramAA* GLRenderer::renderPassProgramAA()
{
    if (!m_renderPassProgramAA)
        m_renderPassProgramAA = make_scoped_ptr(new RenderPassProgramAA(m_context));
    if (!m_renderPassProgramAA->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::renderPassProgramAA::initialize");
        m_renderPassProgramAA->initialize(m_context, m_isUsingBindUniform);
    }
    return m_renderPassProgramAA.get();
}

const GLRenderer::RenderPassMaskProgram* GLRenderer::renderPassMaskProgram()
{
    if (!m_renderPassMaskProgram)
        m_renderPassMaskProgram = make_scoped_ptr(new RenderPassMaskProgram(m_context));
    if (!m_renderPassMaskProgram->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize");
        m_renderPassMaskProgram->initialize(m_context, m_isUsingBindUniform);
    }
    return m_renderPassMaskProgram.get();
}

const GLRenderer::RenderPassMaskProgramAA* GLRenderer::renderPassMaskProgramAA()
{
    if (!m_renderPassMaskProgramAA)
        m_renderPassMaskProgramAA = make_scoped_ptr(new RenderPassMaskProgramAA(m_context));
    if (!m_renderPassMaskProgramAA->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize");
        m_renderPassMaskProgramAA->initialize(m_context, m_isUsingBindUniform);
    }
    return m_renderPassMaskProgramAA.get();
}

const GLRenderer::TileProgram* GLRenderer::tileProgram()
{
    DCHECK(m_tileProgram);
    if (!m_tileProgram->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::tileProgram::initialize");
        m_tileProgram->initialize(m_context, m_isUsingBindUniform);
    }
    return m_tileProgram.get();
}

const GLRenderer::TileProgramOpaque* GLRenderer::tileProgramOpaque()
{
    DCHECK(m_tileProgramOpaque);
    if (!m_tileProgramOpaque->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::tileProgramOpaque::initialize");
        m_tileProgramOpaque->initialize(m_context, m_isUsingBindUniform);
    }
    return m_tileProgramOpaque.get();
}

const GLRenderer::TileProgramAA* GLRenderer::tileProgramAA()
{
    if (!m_tileProgramAA)
        m_tileProgramAA = make_scoped_ptr(new TileProgramAA(m_context));
    if (!m_tileProgramAA->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::tileProgramAA::initialize");
        m_tileProgramAA->initialize(m_context, m_isUsingBindUniform);
    }
    return m_tileProgramAA.get();
}

const GLRenderer::TileProgramSwizzle* GLRenderer::tileProgramSwizzle()
{
    if (!m_tileProgramSwizzle)
        m_tileProgramSwizzle = make_scoped_ptr(new TileProgramSwizzle(m_context));
    if (!m_tileProgramSwizzle->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzle::initialize");
        m_tileProgramSwizzle->initialize(m_context, m_isUsingBindUniform);
    }
    return m_tileProgramSwizzle.get();
}

const GLRenderer::TileProgramSwizzleOpaque* GLRenderer::tileProgramSwizzleOpaque()
{
    if (!m_tileProgramSwizzleOpaque)
        m_tileProgramSwizzleOpaque = make_scoped_ptr(new TileProgramSwizzleOpaque(m_context));
    if (!m_tileProgramSwizzleOpaque->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleOpaque::initialize");
        m_tileProgramSwizzleOpaque->initialize(m_context, m_isUsingBindUniform);
    }
    return m_tileProgramSwizzleOpaque.get();
}

const GLRenderer::TileProgramSwizzleAA* GLRenderer::tileProgramSwizzleAA()
{
    if (!m_tileProgramSwizzleAA)
        m_tileProgramSwizzleAA = make_scoped_ptr(new TileProgramSwizzleAA(m_context));
    if (!m_tileProgramSwizzleAA->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleAA::initialize");
        m_tileProgramSwizzleAA->initialize(m_context, m_isUsingBindUniform);
    }
    return m_tileProgramSwizzleAA.get();
}

const GLRenderer::TextureProgram* GLRenderer::textureProgram()
{
    if (!m_textureProgram)
        m_textureProgram = make_scoped_ptr(new TextureProgram(m_context));
    if (!m_textureProgram->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize");
        m_textureProgram->initialize(m_context, m_isUsingBindUniform);
    }
    return m_textureProgram.get();
}

const GLRenderer::TextureProgramFlip* GLRenderer::textureProgramFlip()
{
    if (!m_textureProgramFlip)
        m_textureProgramFlip = make_scoped_ptr(new TextureProgramFlip(m_context));
    if (!m_textureProgramFlip->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::textureProgramFlip::initialize");
        m_textureProgramFlip->initialize(m_context, m_isUsingBindUniform);
    }
    return m_textureProgramFlip.get();
}

const GLRenderer::TextureIOSurfaceProgram* GLRenderer::textureIOSurfaceProgram()
{
    if (!m_textureIOSurfaceProgram)
        m_textureIOSurfaceProgram = make_scoped_ptr(new TextureIOSurfaceProgram(m_context));
    if (!m_textureIOSurfaceProgram->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::textureIOSurfaceProgram::initialize");
        m_textureIOSurfaceProgram->initialize(m_context, m_isUsingBindUniform);
    }
    return m_textureIOSurfaceProgram.get();
}

const GLRenderer::VideoYUVProgram* GLRenderer::videoYUVProgram()
{
    if (!m_videoYUVProgram)
        m_videoYUVProgram = make_scoped_ptr(new VideoYUVProgram(m_context));
    if (!m_videoYUVProgram->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::videoYUVProgram::initialize");
        m_videoYUVProgram->initialize(m_context, m_isUsingBindUniform);
    }
    return m_videoYUVProgram.get();
}

const GLRenderer::VideoStreamTextureProgram* GLRenderer::videoStreamTextureProgram()
{
    if (!m_videoStreamTextureProgram)
        m_videoStreamTextureProgram = make_scoped_ptr(new VideoStreamTextureProgram(m_context));
    if (!m_videoStreamTextureProgram->initialized()) {
        TRACE_EVENT0("cc", "GLRenderer::streamTextureProgram::initialize");
        m_videoStreamTextureProgram->initialize(m_context, m_isUsingBindUniform);
    }
    return m_videoStreamTextureProgram.get();
}

void GLRenderer::cleanupSharedObjects()
{
    makeContextCurrent();

    m_sharedGeometry.reset();

    if (m_tileProgram)
        m_tileProgram->cleanup(m_context);
    if (m_tileProgramOpaque)
        m_tileProgramOpaque->cleanup(m_context);
    if (m_tileProgramSwizzle)
        m_tileProgramSwizzle->cleanup(m_context);
    if (m_tileProgramSwizzleOpaque)
        m_tileProgramSwizzleOpaque->cleanup(m_context);
    if (m_tileProgramAA)
        m_tileProgramAA->cleanup(m_context);
    if (m_tileProgramSwizzleAA)
        m_tileProgramSwizzleAA->cleanup(m_context);
    if (m_tileCheckerboardProgram)
        m_tileCheckerboardProgram->cleanup(m_context);

    if (m_renderPassMaskProgram)
        m_renderPassMaskProgram->cleanup(m_context);
    if (m_renderPassProgram)
        m_renderPassProgram->cleanup(m_context);
    if (m_renderPassMaskProgramAA)
        m_renderPassMaskProgramAA->cleanup(m_context);
    if (m_renderPassProgramAA)
        m_renderPassProgramAA->cleanup(m_context);

    if (m_textureProgram)
        m_textureProgram->cleanup(m_context);
    if (m_textureProgramFlip)
        m_textureProgramFlip->cleanup(m_context);
    if (m_textureIOSurfaceProgram)
        m_textureIOSurfaceProgram->cleanup(m_context);

    if (m_videoYUVProgram)
        m_videoYUVProgram->cleanup(m_context);
    if (m_videoStreamTextureProgram)
        m_videoStreamTextureProgram->cleanup(m_context);

    if (m_solidColorProgram)
        m_solidColorProgram->cleanup(m_context);

    if (m_offscreenFramebufferId)
        GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId));

    releaseRenderPassTextures();
}

bool GLRenderer::isContextLost()
{
    return (m_context->getGraphicsResetStatusARB() != GL_NO_ERROR);
}

}  // namespace cc
