Home | History | Annotate | Download | only in output
      1 // Copyright 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "cc/output/gl_renderer.h"
      6 
      7 #include <algorithm>
      8 #include <limits>
      9 #include <set>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "base/debug/trace_event.h"
     14 #include "base/logging.h"
     15 #include "base/strings/string_split.h"
     16 #include "base/strings/string_util.h"
     17 #include "base/strings/stringprintf.h"
     18 #include "build/build_config.h"
     19 #include "cc/base/math_util.h"
     20 #include "cc/layers/video_layer_impl.h"
     21 #include "cc/output/compositor_frame.h"
     22 #include "cc/output/compositor_frame_metadata.h"
     23 #include "cc/output/context_provider.h"
     24 #include "cc/output/copy_output_request.h"
     25 #include "cc/output/geometry_binding.h"
     26 #include "cc/output/gl_frame_data.h"
     27 #include "cc/output/output_surface.h"
     28 #include "cc/output/render_surface_filters.h"
     29 #include "cc/quads/picture_draw_quad.h"
     30 #include "cc/quads/render_pass.h"
     31 #include "cc/quads/stream_video_draw_quad.h"
     32 #include "cc/quads/texture_draw_quad.h"
     33 #include "cc/resources/layer_quad.h"
     34 #include "cc/resources/scoped_resource.h"
     35 #include "cc/resources/sync_point_helper.h"
     36 #include "cc/trees/damage_tracker.h"
     37 #include "cc/trees/proxy.h"
     38 #include "cc/trees/single_thread_proxy.h"
     39 #include "gpu/GLES2/gl2extchromium.h"
     40 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
     41 #include "third_party/khronos/GLES2/gl2.h"
     42 #include "third_party/khronos/GLES2/gl2ext.h"
     43 #include "third_party/skia/include/core/SkBitmap.h"
     44 #include "third_party/skia/include/core/SkColor.h"
     45 #include "third_party/skia/include/core/SkColorFilter.h"
     46 #include "third_party/skia/include/core/SkSurface.h"
     47 #include "third_party/skia/include/gpu/GrContext.h"
     48 #include "third_party/skia/include/gpu/GrTexture.h"
     49 #include "third_party/skia/include/gpu/SkGpuDevice.h"
     50 #include "third_party/skia/include/gpu/SkGrTexturePixelRef.h"
     51 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
     52 #include "ui/gfx/quad_f.h"
     53 #include "ui/gfx/rect_conversions.h"
     54 
     55 using WebKit::WebGraphicsContext3D;
     56 
     57 namespace cc {
     58 
     59 namespace {
     60 
     61 // TODO(epenner): This should probably be moved to output surface.
     62 //
     63 // This implements a simple fence based on client side swaps.
     64 // This is to isolate the ResourceProvider from 'frames' which
     65 // it shouldn't need to care about, while still allowing us to
     66 // enforce good texture recycling behavior strictly throughout
     67 // the compositor (don't recycle a texture while it's in use).
     68 class SimpleSwapFence : public ResourceProvider::Fence {
     69  public:
     70   SimpleSwapFence() : has_passed_(false) {}
     71   virtual bool HasPassed() OVERRIDE { return has_passed_; }
     72   void SetHasPassed() { has_passed_ = true; }
     73  private:
     74   virtual ~SimpleSwapFence() {}
     75   bool has_passed_;
     76 };
     77 
     78 bool NeedsIOSurfaceReadbackWorkaround() {
     79 #if defined(OS_MACOSX)
     80   // This isn't strictly required in DumpRenderTree-mode when Mesa is used,
     81   // but it doesn't seem to hurt.
     82   return true;
     83 #else
     84   return false;
     85 #endif
     86 }
     87 
     88 Float4 UVTransform(const TextureDrawQuad* quad) {
     89   gfx::PointF uv0 = quad->uv_top_left;
     90   gfx::PointF uv1 = quad->uv_bottom_right;
     91   Float4 xform = { { uv0.x(), uv0.y(), uv1.x() - uv0.x(), uv1.y() - uv0.y() } };
     92   if (quad->flipped) {
     93     xform.data[1] = 1.0f - xform.data[1];
     94     xform.data[3] = -xform.data[3];
     95   }
     96   return xform;
     97 }
     98 
     99 Float4 PremultipliedColor(SkColor color) {
    100   const float factor = 1.0f / 255.0f;
    101   const float alpha = SkColorGetA(color) * factor;
    102 
    103   Float4 result = { {
    104       SkColorGetR(color) * factor * alpha,
    105       SkColorGetG(color) * factor * alpha,
    106       SkColorGetB(color) * factor * alpha,
    107       alpha
    108   } };
    109   return result;
    110 }
    111 
    112 // Smallest unit that impact anti-aliasing output. We use this to
    113 // determine when anti-aliasing is unnecessary.
    114 const float kAntiAliasingEpsilon = 1.0f / 1024.0f;
    115 
    116 }  // anonymous namespace
    117 
    118 struct GLRenderer::PendingAsyncReadPixels {
    119   PendingAsyncReadPixels() : buffer(0) {}
    120 
    121   scoped_ptr<CopyOutputRequest> copy_request;
    122   base::CancelableClosure finished_read_pixels_callback;
    123   unsigned buffer;
    124 
    125  private:
    126   DISALLOW_COPY_AND_ASSIGN(PendingAsyncReadPixels);
    127 };
    128 
    129 scoped_ptr<GLRenderer> GLRenderer::Create(RendererClient* client,
    130                                           OutputSurface* output_surface,
    131                                           ResourceProvider* resource_provider,
    132                                           int highp_threshold_min,
    133                                           bool use_skia_gpu_backend) {
    134   scoped_ptr<GLRenderer> renderer(new GLRenderer(
    135       client, output_surface, resource_provider, highp_threshold_min));
    136   if (!renderer->Initialize())
    137     return scoped_ptr<GLRenderer>();
    138   if (use_skia_gpu_backend) {
    139     renderer->InitializeGrContext();
    140     DCHECK(renderer->CanUseSkiaGPUBackend())
    141         << "Requested Skia GPU backend, but can't use it.";
    142   }
    143 
    144   return renderer.Pass();
    145 }
    146 
    147 GLRenderer::GLRenderer(RendererClient* client,
    148                        OutputSurface* output_surface,
    149                        ResourceProvider* resource_provider,
    150                        int highp_threshold_min)
    151     : DirectRenderer(client, output_surface, resource_provider),
    152       offscreen_framebuffer_id_(0),
    153       shared_geometry_quad_(gfx::RectF(-0.5f, -0.5f, 1.0f, 1.0f)),
    154       context_(output_surface->context3d()),
    155       is_backbuffer_discarded_(false),
    156       discard_backbuffer_when_not_visible_(false),
    157       is_using_bind_uniform_(false),
    158       visible_(true),
    159       is_scissor_enabled_(false),
    160       stencil_shadow_(false),
    161       blend_shadow_(false),
    162       highp_threshold_min_(highp_threshold_min),
    163       highp_threshold_cache_(0),
    164       offscreen_context_labelled_(false),
    165       on_demand_tile_raster_resource_id_(0),
    166       weak_factory_(this) {
    167   DCHECK(context_);
    168 }
    169 
    170 bool GLRenderer::Initialize() {
    171   if (!context_->makeContextCurrent())
    172     return false;
    173 
    174   std::string unique_context_name = base::StringPrintf(
    175       "%s-%p",
    176       Settings().compositor_name.c_str(),
    177       context_);
    178   context_->pushGroupMarkerEXT(unique_context_name.c_str());
    179 
    180   std::string extensions_string =
    181       UTF16ToASCII(context_->getString(GL_EXTENSIONS));
    182   std::vector<std::string> extensions_list;
    183   base::SplitString(extensions_string, ' ', &extensions_list);
    184   std::set<std::string> extensions(extensions_list.begin(),
    185                                    extensions_list.end());
    186 
    187   capabilities_.using_partial_swap =
    188       Settings().partial_swap_enabled &&
    189       extensions.count("GL_CHROMIUM_post_sub_buffer");
    190 
    191   capabilities_.using_set_visibility =
    192       extensions.count("GL_CHROMIUM_set_visibility") > 0;
    193 
    194   if (extensions.count("GL_CHROMIUM_iosurface") > 0)
    195     DCHECK_GT(extensions.count("GL_ARB_texture_rectangle"), 0u);
    196 
    197   capabilities_.using_egl_image =
    198       extensions.count("GL_OES_EGL_image_external") > 0;
    199 
    200   capabilities_.max_texture_size = resource_provider_->max_texture_size();
    201   capabilities_.best_texture_format = resource_provider_->best_texture_format();
    202 
    203   // The updater can access textures while the GLRenderer is using them.
    204   capabilities_.allow_partial_texture_updates = true;
    205 
    206   // Check for texture fast paths. Currently we always use MO8 textures,
    207   // so we only need to avoid POT textures if we have an NPOT fast-path.
    208   capabilities_.avoid_pow2_textures =
    209       extensions.count("GL_CHROMIUM_fast_NPOT_MO8_textures") > 0;
    210 
    211   capabilities_.using_offscreen_context3d = true;
    212 
    213   capabilities_.using_map_image =
    214       extensions.count("GL_CHROMIUM_map_image") > 0 &&
    215       Settings().use_map_image;
    216 
    217   is_using_bind_uniform_ =
    218       extensions.count("GL_CHROMIUM_bind_uniform_location") > 0;
    219 
    220   if (!InitializeSharedObjects())
    221     return false;
    222 
    223   // Make sure the viewport and context gets initialized, even if it is to zero.
    224   ViewportChanged();
    225   return true;
    226 }
    227 
    228 void GLRenderer::InitializeGrContext() {
    229   skia::RefPtr<GrGLInterface> interface = skia::AdoptRef(
    230       context_->createGrGLInterface());
    231   if (!interface)
    232     return;
    233 
    234   gr_context_ = skia::AdoptRef(GrContext::Create(
    235       kOpenGL_GrBackend,
    236       reinterpret_cast<GrBackendContext>(interface.get())));
    237   ReinitializeGrCanvas();
    238 }
    239 
    240 GLRenderer::~GLRenderer() {
    241   while (!pending_async_read_pixels_.empty()) {
    242     PendingAsyncReadPixels* pending_read = pending_async_read_pixels_.back();
    243     pending_read->finished_read_pixels_callback.Cancel();
    244     pending_async_read_pixels_.pop_back();
    245   }
    246 
    247   context_->setMemoryAllocationChangedCallbackCHROMIUM(NULL);
    248   CleanupSharedObjects();
    249 }
    250 
    251 const RendererCapabilities& GLRenderer::Capabilities() const {
    252   return capabilities_;
    253 }
    254 
    255 WebGraphicsContext3D* GLRenderer::Context() { return context_; }
    256 
    257 void GLRenderer::DebugGLCall(WebGraphicsContext3D* context,
    258                              const char* command,
    259                              const char* file,
    260                              int line) {
    261   unsigned error = context->getError();
    262   if (error != GL_NO_ERROR)
    263     LOG(ERROR) << "GL command failed: File: " << file << "\n\tLine " << line
    264                << "\n\tcommand: " << command << ", error "
    265                << static_cast<int>(error) << "\n";
    266 }
    267 
    268 void GLRenderer::SetVisible(bool visible) {
    269   if (visible_ == visible)
    270     return;
    271   visible_ = visible;
    272 
    273   EnforceMemoryPolicy();
    274 
    275   // TODO(jamesr): Replace setVisibilityCHROMIUM() with an extension to
    276   // explicitly manage front/backbuffers
    277   // crbug.com/116049
    278   if (capabilities_.using_set_visibility)
    279     context_->setVisibilityCHROMIUM(visible);
    280 }
    281 
    282 void GLRenderer::SendManagedMemoryStats(size_t bytes_visible,
    283                                         size_t bytes_visible_and_nearby,
    284                                         size_t bytes_allocated) {
    285   WebKit::WebGraphicsManagedMemoryStats stats;
    286   stats.bytesVisible = bytes_visible;
    287   stats.bytesVisibleAndNearby = bytes_visible_and_nearby;
    288   stats.bytesAllocated = bytes_allocated;
    289   stats.backbufferRequested = !is_backbuffer_discarded_;
    290   context_->sendManagedMemoryStatsCHROMIUM(&stats);
    291 }
    292 
    293 void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_.clear(); }
    294 
    295 void GLRenderer::ViewportChanged() {
    296   ReinitializeGrCanvas();
    297 }
    298 
    299 void GLRenderer::ClearFramebuffer(DrawingFrame* frame) {
    300   // It's unsafe to clear when we have a stencil test because glClear ignores
    301   // stencil.
    302   if (client_->ExternalStencilTestEnabled() &&
    303       frame->current_render_pass == frame->root_render_pass) {
    304     DCHECK(!frame->current_render_pass->has_transparent_background);
    305     return;
    306   }
    307 
    308   // On DEBUG builds, opaque render passes are cleared to blue to easily see
    309   // regions that were not drawn on the screen.
    310   if (frame->current_render_pass->has_transparent_background)
    311     GLC(context_, context_->clearColor(0, 0, 0, 0));
    312   else
    313     GLC(context_, context_->clearColor(0, 0, 1, 1));
    314 
    315   bool always_clear = false;
    316 #ifndef NDEBUG
    317   always_clear = true;
    318 #endif
    319   if (always_clear || frame->current_render_pass->has_transparent_background) {
    320     GLbitfield clear_bits = GL_COLOR_BUFFER_BIT;
    321     // Only the Skia GPU backend uses the stencil buffer.  No need to clear it
    322     // otherwise.
    323     if (always_clear || CanUseSkiaGPUBackend()) {
    324       GLC(context_, context_->clearStencil(0));
    325       clear_bits |= GL_STENCIL_BUFFER_BIT;
    326     }
    327     context_->clear(clear_bits);
    328   }
    329 }
    330 
    331 void GLRenderer::BeginDrawingFrame(DrawingFrame* frame) {
    332   if (client_->DeviceViewport().IsEmpty())
    333     return;
    334 
    335   TRACE_EVENT0("cc", "GLRenderer::DrawLayers");
    336 
    337   MakeContextCurrent();
    338 
    339   ReinitializeGLState();
    340 }
    341 
    342 void GLRenderer::DoNoOp() {
    343   GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, 0));
    344   GLC(context_, context_->flush());
    345 }
    346 
    347 void GLRenderer::DoDrawQuad(DrawingFrame* frame, const DrawQuad* quad) {
    348   DCHECK(quad->rect.Contains(quad->visible_rect));
    349   if (quad->material != DrawQuad::TEXTURE_CONTENT) {
    350     FlushTextureQuadCache();
    351   }
    352 
    353   switch (quad->material) {
    354     case DrawQuad::INVALID:
    355       NOTREACHED();
    356       break;
    357     case DrawQuad::CHECKERBOARD:
    358       DrawCheckerboardQuad(frame, CheckerboardDrawQuad::MaterialCast(quad));
    359       break;
    360     case DrawQuad::DEBUG_BORDER:
    361       DrawDebugBorderQuad(frame, DebugBorderDrawQuad::MaterialCast(quad));
    362       break;
    363     case DrawQuad::IO_SURFACE_CONTENT:
    364       DrawIOSurfaceQuad(frame, IOSurfaceDrawQuad::MaterialCast(quad));
    365       break;
    366     case DrawQuad::PICTURE_CONTENT:
    367       DrawPictureQuad(frame, PictureDrawQuad::MaterialCast(quad));
    368       break;
    369     case DrawQuad::RENDER_PASS:
    370       DrawRenderPassQuad(frame, RenderPassDrawQuad::MaterialCast(quad));
    371       break;
    372     case DrawQuad::SOLID_COLOR:
    373       DrawSolidColorQuad(frame, SolidColorDrawQuad::MaterialCast(quad));
    374       break;
    375     case DrawQuad::STREAM_VIDEO_CONTENT:
    376       DrawStreamVideoQuad(frame, StreamVideoDrawQuad::MaterialCast(quad));
    377       break;
    378     case DrawQuad::TEXTURE_CONTENT:
    379       EnqueueTextureQuad(frame, TextureDrawQuad::MaterialCast(quad));
    380       break;
    381     case DrawQuad::TILED_CONTENT:
    382       DrawTileQuad(frame, TileDrawQuad::MaterialCast(quad));
    383       break;
    384     case DrawQuad::YUV_VIDEO_CONTENT:
    385       DrawYUVVideoQuad(frame, YUVVideoDrawQuad::MaterialCast(quad));
    386       break;
    387   }
    388 }
    389 
    390 void GLRenderer::DrawCheckerboardQuad(const DrawingFrame* frame,
    391                                       const CheckerboardDrawQuad* quad) {
    392   SetBlendEnabled(quad->ShouldDrawWithBlending());
    393 
    394   const TileCheckerboardProgram* program = GetTileCheckerboardProgram();
    395   DCHECK(program && (program->initialized() || IsContextLost()));
    396   SetUseProgram(program->program());
    397 
    398   SkColor color = quad->color;
    399   GLC(Context(),
    400       Context()->uniform4f(program->fragment_shader().color_location(),
    401                            SkColorGetR(color) * (1.0f / 255.0f),
    402                            SkColorGetG(color) * (1.0f / 255.0f),
    403                            SkColorGetB(color) * (1.0f / 255.0f),
    404                            1));
    405 
    406   const int checkerboard_width = 16;
    407   float frequency = 1.0f / checkerboard_width;
    408 
    409   gfx::Rect tile_rect = quad->rect;
    410   float tex_offset_x = tile_rect.x() % checkerboard_width;
    411   float tex_offset_y = tile_rect.y() % checkerboard_width;
    412   float tex_scale_x = tile_rect.width();
    413   float tex_scale_y = tile_rect.height();
    414   GLC(Context(),
    415       Context()->uniform4f(program->fragment_shader().tex_transform_location(),
    416                            tex_offset_x,
    417                            tex_offset_y,
    418                            tex_scale_x,
    419                            tex_scale_y));
    420 
    421   GLC(Context(),
    422       Context()->uniform1f(program->fragment_shader().frequency_location(),
    423                            frequency));
    424 
    425   SetShaderOpacity(quad->opacity(),
    426                    program->fragment_shader().alpha_location());
    427   DrawQuadGeometry(frame,
    428                    quad->quadTransform(),
    429                    quad->rect,
    430                    program->vertex_shader().matrix_location());
    431 }
    432 
    433 void GLRenderer::DrawDebugBorderQuad(const DrawingFrame* frame,
    434                                      const DebugBorderDrawQuad* quad) {
    435   SetBlendEnabled(quad->ShouldDrawWithBlending());
    436 
    437   static float gl_matrix[16];
    438   const DebugBorderProgram* program = GetDebugBorderProgram();
    439   DCHECK(program && (program->initialized() || IsContextLost()));
    440   SetUseProgram(program->program());
    441 
    442   // Use the full quad_rect for debug quads to not move the edges based on
    443   // partial swaps.
    444   gfx::Rect layer_rect = quad->rect;
    445   gfx::Transform render_matrix = quad->quadTransform();
    446   render_matrix.Translate(0.5f * layer_rect.width() + layer_rect.x(),
    447                           0.5f * layer_rect.height() + layer_rect.y());
    448   render_matrix.Scale(layer_rect.width(), layer_rect.height());
    449   GLRenderer::ToGLMatrix(&gl_matrix[0],
    450                          frame->projection_matrix * render_matrix);
    451   GLC(Context(),
    452       Context()->uniformMatrix4fv(
    453           program->vertex_shader().matrix_location(), 1, false, &gl_matrix[0]));
    454 
    455   SkColor color = quad->color;
    456   float alpha = SkColorGetA(color) * (1.0f / 255.0f);
    457 
    458   GLC(Context(),
    459       Context()->uniform4f(program->fragment_shader().color_location(),
    460                            (SkColorGetR(color) * (1.0f / 255.0f)) * alpha,
    461                            (SkColorGetG(color) * (1.0f / 255.0f)) * alpha,
    462                            (SkColorGetB(color) * (1.0f / 255.0f)) * alpha,
    463                            alpha));
    464 
    465   GLC(Context(), Context()->lineWidth(quad->width));
    466 
    467   // The indices for the line are stored in the same array as the triangle
    468   // indices.
    469   GLC(Context(),
    470       Context()->drawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0));
    471 }
    472 
    473 static inline SkBitmap ApplyFilters(GLRenderer* renderer,
    474                                     const FilterOperations& filters,
    475                                     ScopedResource* source_texture_resource) {
    476   if (filters.IsEmpty())
    477     return SkBitmap();
    478 
    479   ContextProvider* offscreen_contexts =
    480       renderer->resource_provider()->offscreen_context_provider();
    481   if (!offscreen_contexts || !offscreen_contexts->GrContext())
    482     return SkBitmap();
    483 
    484   ResourceProvider::ScopedWriteLockGL lock(renderer->resource_provider(),
    485                                            source_texture_resource->id());
    486 
    487   // Flush the compositor context to ensure that textures there are available
    488   // in the shared context.  Do this after locking/creating the compositor
    489   // texture.
    490   renderer->resource_provider()->Flush();
    491 
    492   // Make sure skia uses the correct GL context.
    493   offscreen_contexts->Context3d()->makeContextCurrent();
    494 
    495   // Lazily label this context.
    496   renderer->LazyLabelOffscreenContext();
    497 
    498   SkBitmap source =
    499       RenderSurfaceFilters::Apply(filters,
    500                                   lock.texture_id(),
    501                                   source_texture_resource->size(),
    502                                   offscreen_contexts->GrContext());
    503 
    504   // Flush skia context so that all the rendered stuff appears on the
    505   // texture.
    506   offscreen_contexts->GrContext()->flush();
    507 
    508   // Flush the GL context so rendering results from this context are
    509   // visible in the compositor's context.
    510   offscreen_contexts->Context3d()->flush();
    511 
    512   // Use the compositor's GL context again.
    513   renderer->resource_provider()->GraphicsContext3D()->makeContextCurrent();
    514   return source;
    515 }
    516 
    517 static SkBitmap ApplyImageFilter(GLRenderer* renderer,
    518                                  SkImageFilter* filter,
    519                                  ScopedResource* source_texture_resource) {
    520   if (!filter)
    521     return SkBitmap();
    522 
    523   ContextProvider* offscreen_contexts =
    524       renderer->resource_provider()->offscreen_context_provider();
    525   if (!offscreen_contexts || !offscreen_contexts->GrContext())
    526     return SkBitmap();
    527 
    528   ResourceProvider::ScopedWriteLockGL lock(renderer->resource_provider(),
    529                                            source_texture_resource->id());
    530 
    531   // Flush the compositor context to ensure that textures there are available
    532   // in the shared context.  Do this after locking/creating the compositor
    533   // texture.
    534   renderer->resource_provider()->Flush();
    535 
    536   // Make sure skia uses the correct GL context.
    537   offscreen_contexts->Context3d()->makeContextCurrent();
    538 
    539   // Lazily label this context.
    540   renderer->LazyLabelOffscreenContext();
    541 
    542   // Wrap the source texture in a Ganesh platform texture.
    543   GrBackendTextureDesc backend_texture_description;
    544   backend_texture_description.fWidth = source_texture_resource->size().width();
    545   backend_texture_description.fHeight =
    546       source_texture_resource->size().height();
    547   backend_texture_description.fConfig = kSkia8888_GrPixelConfig;
    548   backend_texture_description.fTextureHandle = lock.texture_id();
    549   backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin;
    550   skia::RefPtr<GrTexture> texture =
    551       skia::AdoptRef(offscreen_contexts->GrContext()->wrapBackendTexture(
    552           backend_texture_description));
    553 
    554   // Place the platform texture inside an SkBitmap.
    555   SkBitmap source;
    556   source.setConfig(SkBitmap::kARGB_8888_Config,
    557                    source_texture_resource->size().width(),
    558                    source_texture_resource->size().height());
    559   skia::RefPtr<SkGrPixelRef> pixel_ref =
    560       skia::AdoptRef(new SkGrPixelRef(texture.get()));
    561   source.setPixelRef(pixel_ref.get());
    562 
    563   // Create a scratch texture for backing store.
    564   GrTextureDesc desc;
    565   desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
    566   desc.fSampleCnt = 0;
    567   desc.fWidth = source.width();
    568   desc.fHeight = source.height();
    569   desc.fConfig = kSkia8888_GrPixelConfig;
    570   desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
    571   GrAutoScratchTexture scratch_texture(
    572       offscreen_contexts->GrContext(), desc, GrContext::kExact_ScratchTexMatch);
    573   skia::RefPtr<GrTexture> backing_store =
    574       skia::AdoptRef(scratch_texture.detach());
    575 
    576   // Create a device and canvas using that backing store.
    577   SkGpuDevice device(offscreen_contexts->GrContext(), backing_store.get());
    578   SkCanvas canvas(&device);
    579 
    580   // Draw the source bitmap through the filter to the canvas.
    581   SkPaint paint;
    582   paint.setImageFilter(filter);
    583   canvas.clear(SK_ColorTRANSPARENT);
    584   canvas.drawSprite(source, 0, 0, &paint);
    585 
    586   // Flush skia context so that all the rendered stuff appears on the
    587   // texture.
    588   offscreen_contexts->GrContext()->flush();
    589 
    590   // Flush the GL context so rendering results from this context are
    591   // visible in the compositor's context.
    592   offscreen_contexts->Context3d()->flush();
    593 
    594   // Use the compositor's GL context again.
    595   renderer->resource_provider()->GraphicsContext3D()->makeContextCurrent();
    596 
    597   return device.accessBitmap(false);
    598 }
    599 
    600 scoped_ptr<ScopedResource> GLRenderer::DrawBackgroundFilters(
    601     DrawingFrame* frame,
    602     const RenderPassDrawQuad* quad,
    603     const gfx::Transform& contents_device_transform,
    604     const gfx::Transform& contents_device_transform_inverse) {
    605   // This method draws a background filter, which applies a filter to any pixels
    606   // behind the quad and seen through its background.  The algorithm works as
    607   // follows:
    608   // 1. Compute a bounding box around the pixels that will be visible through
    609   // the quad.
    610   // 2. Read the pixels in the bounding box into a buffer R.
    611   // 3. Apply the background filter to R, so that it is applied in the pixels'
    612   // coordinate space.
    613   // 4. Apply the quad's inverse transform to map the pixels in R into the
    614   // quad's content space. This implicitly clips R by the content bounds of the
    615   // quad since the destination texture has bounds matching the quad's content.
    616   // 5. Draw the background texture for the contents using the same transform as
    617   // used to draw the contents itself. This is done without blending to replace
    618   // the current background pixels with the new filtered background.
    619   // 6. Draw the contents of the quad over drop of the new background with
    620   // blending, as per usual. The filtered background pixels will show through
    621   // any non-opaque pixels in this draws.
    622   //
    623   // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
    624 
    625   // TODO(danakj): When this algorithm changes, update
    626   // LayerTreeHost::PrioritizeTextures() accordingly.
    627 
    628   FilterOperations filters =
    629       RenderSurfaceFilters::Optimize(quad->background_filters);
    630   DCHECK(!filters.IsEmpty());
    631 
    632   // TODO(danakj): We only allow background filters on an opaque render surface
    633   // because other surfaces may contain translucent pixels, and the contents
    634   // behind those translucent pixels wouldn't have the filter applied.
    635   if (frame->current_render_pass->has_transparent_background)
    636     return scoped_ptr<ScopedResource>();
    637   DCHECK(!frame->current_texture);
    638 
    639   // TODO(danakj): Do a single readback for both the surface and replica and
    640   // cache the filtered results (once filter textures are not reused).
    641   gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect(
    642       contents_device_transform, SharedGeometryQuad().BoundingBox()));
    643 
    644   int top, right, bottom, left;
    645   filters.GetOutsets(&top, &right, &bottom, &left);
    646   window_rect.Inset(-left, -top, -right, -bottom);
    647 
    648   window_rect.Intersect(
    649       MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect));
    650 
    651   scoped_ptr<ScopedResource> device_background_texture =
    652       ScopedResource::create(resource_provider_);
    653   if (!device_background_texture->Allocate(window_rect.size(),
    654                                            GL_RGB,
    655                                            ResourceProvider::TextureUsageAny)) {
    656     return scoped_ptr<ScopedResource>();
    657   } else {
    658     ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
    659                                              device_background_texture->id());
    660     GetFramebufferTexture(lock.texture_id(),
    661                           device_background_texture->format(),
    662                           window_rect);
    663   }
    664 
    665   SkBitmap filtered_device_background =
    666       ApplyFilters(this, filters, device_background_texture.get());
    667   if (!filtered_device_background.getTexture())
    668     return scoped_ptr<ScopedResource>();
    669 
    670   GrTexture* texture =
    671       reinterpret_cast<GrTexture*>(filtered_device_background.getTexture());
    672   int filtered_device_background_texture_id = texture->getTextureHandle();
    673 
    674   scoped_ptr<ScopedResource> background_texture =
    675       ScopedResource::create(resource_provider_);
    676   if (!background_texture->Allocate(quad->rect.size(),
    677                                     GL_RGBA,
    678                                     ResourceProvider::TextureUsageFramebuffer))
    679     return scoped_ptr<ScopedResource>();
    680 
    681   const RenderPass* target_render_pass = frame->current_render_pass;
    682   bool using_background_texture =
    683       UseScopedTexture(frame, background_texture.get(), quad->rect);
    684 
    685   if (using_background_texture) {
    686     // Copy the readback pixels from device to the background texture for the
    687     // surface.
    688     gfx::Transform device_to_framebuffer_transform;
    689     device_to_framebuffer_transform.Translate(
    690         quad->rect.width() * 0.5f + quad->rect.x(),
    691         quad->rect.height() * 0.5f + quad->rect.y());
    692     device_to_framebuffer_transform.Scale(quad->rect.width(),
    693                                           quad->rect.height());
    694     device_to_framebuffer_transform.PreconcatTransform(
    695         contents_device_transform_inverse);
    696 
    697 #ifndef NDEBUG
    698     GLC(Context(), Context()->clearColor(0, 0, 1, 1));
    699     Context()->clear(GL_COLOR_BUFFER_BIT);
    700 #endif
    701 
    702     // The filtered_deveice_background_texture is oriented the same as the frame
    703     // buffer. The transform we are copying with has a vertical flip, as well as
    704     // the |device_to_framebuffer_transform|, which cancel each other out. So do
    705     // not flip the contents in the shader to maintain orientation.
    706     bool flip_vertically = false;
    707 
    708     CopyTextureToFramebuffer(frame,
    709                              filtered_device_background_texture_id,
    710                              window_rect,
    711                              device_to_framebuffer_transform,
    712                              flip_vertically);
    713   }
    714 
    715   UseRenderPass(frame, target_render_pass);
    716 
    717   if (!using_background_texture)
    718     return scoped_ptr<ScopedResource>();
    719   return background_texture.Pass();
    720 }
    721 
    722 void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame,
    723                                     const RenderPassDrawQuad* quad) {
    724   SetBlendEnabled(quad->ShouldDrawWithBlending());
    725 
    726   CachedResource* contents_texture =
    727       render_pass_textures_.get(quad->render_pass_id);
    728   if (!contents_texture || !contents_texture->id())
    729     return;
    730 
    731   gfx::Transform quad_rect_matrix;
    732   QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect);
    733   gfx::Transform contents_device_transform =
    734       frame->window_matrix * frame->projection_matrix * quad_rect_matrix;
    735   contents_device_transform.FlattenTo2d();
    736 
    737   // Can only draw surface if device matrix is invertible.
    738   gfx::Transform contents_device_transform_inverse(
    739       gfx::Transform::kSkipInitialization);
    740   if (!contents_device_transform.GetInverse(&contents_device_transform_inverse))
    741     return;
    742 
    743   scoped_ptr<ScopedResource> background_texture;
    744   if (!quad->background_filters.IsEmpty()) {
    745     // The pixels from the filtered background should completely replace the
    746     // current pixel values.
    747     bool disable_blending = blend_enabled();
    748     if (disable_blending)
    749       SetBlendEnabled(false);
    750 
    751     background_texture = DrawBackgroundFilters(
    752         frame,
    753         quad,
    754         contents_device_transform,
    755         contents_device_transform_inverse);
    756 
    757     if (disable_blending)
    758       SetBlendEnabled(true);
    759   }
    760 
    761   // TODO(senorblanco): Cache this value so that we don't have to do it for both
    762   // the surface and its replica.  Apply filters to the contents texture.
    763   SkBitmap filter_bitmap;
    764   SkScalar color_matrix[20];
    765   bool use_color_matrix = false;
    766   if (quad->filter) {
    767     skia::RefPtr<SkColorFilter> cf;
    768 
    769     {
    770       SkColorFilter* colorfilter_rawptr = NULL;
    771       quad->filter->asColorFilter(&colorfilter_rawptr);
    772       cf = skia::AdoptRef(colorfilter_rawptr);
    773     }
    774 
    775     if (cf && cf->asColorMatrix(color_matrix) && !quad->filter->getInput(0)) {
    776       // We have a single color matrix as a filter; apply it locally
    777       // in the compositor.
    778       use_color_matrix = true;
    779     } else {
    780       filter_bitmap =
    781           ApplyImageFilter(this, quad->filter.get(), contents_texture);
    782     }
    783   } else if (!quad->filters.IsEmpty()) {
    784     FilterOperations optimized_filters =
    785         RenderSurfaceFilters::Optimize(quad->filters);
    786 
    787     if ((optimized_filters.size() == 1) &&
    788         (optimized_filters.at(0).type() == FilterOperation::COLOR_MATRIX)) {
    789       memcpy(
    790           color_matrix, optimized_filters.at(0).matrix(), sizeof(color_matrix));
    791       use_color_matrix = true;
    792     } else {
    793       filter_bitmap = ApplyFilters(this, optimized_filters, contents_texture);
    794     }
    795   }
    796 
    797   // Draw the background texture if there is one.
    798   if (background_texture) {
    799     DCHECK(background_texture->size() == quad->rect.size());
    800     ResourceProvider::ScopedReadLockGL lock(resource_provider_,
    801                                             background_texture->id());
    802 
    803     // The background_texture is oriented the same as the frame buffer. The
    804     // transform we are copying with has a vertical flip, so flip the contents
    805     // in the shader to maintain orientation
    806     bool flip_vertically = true;
    807 
    808     CopyTextureToFramebuffer(frame,
    809                              lock.texture_id(),
    810                              quad->rect,
    811                              quad->quadTransform(),
    812                              flip_vertically);
    813   }
    814 
    815   bool clipped = false;
    816   gfx::QuadF device_quad = MathUtil::MapQuad(
    817       contents_device_transform, SharedGeometryQuad(), &clipped);
    818   LayerQuad device_layer_bounds(gfx::QuadF(device_quad.BoundingBox()));
    819   LayerQuad device_layer_edges(device_quad);
    820 
    821   // Use anti-aliasing programs only when necessary.
    822   bool use_aa = !clipped &&
    823       (!device_quad.IsRectilinear() ||
    824        !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(),
    825                                          kAntiAliasingEpsilon));
    826   if (use_aa) {
    827     device_layer_bounds.InflateAntiAliasingDistance();
    828     device_layer_edges.InflateAntiAliasingDistance();
    829   }
    830 
    831   scoped_ptr<ResourceProvider::ScopedReadLockGL> mask_resource_lock;
    832   unsigned mask_texture_id = 0;
    833   if (quad->mask_resource_id) {
    834     mask_resource_lock.reset(new ResourceProvider::ScopedReadLockGL(
    835         resource_provider_, quad->mask_resource_id));
    836     mask_texture_id = mask_resource_lock->texture_id();
    837   }
    838 
    839   // TODO(danakj): use the background_texture and blend the background in with
    840   // this draw instead of having a separate copy of the background texture.
    841 
    842   scoped_ptr<ResourceProvider::ScopedReadLockGL> contents_resource_lock;
    843   if (filter_bitmap.getTexture()) {
    844     GrTexture* texture =
    845         reinterpret_cast<GrTexture*>(filter_bitmap.getTexture());
    846     DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
    847     Context()->bindTexture(GL_TEXTURE_2D, texture->getTextureHandle());
    848   } else {
    849     contents_resource_lock = make_scoped_ptr(
    850         new ResourceProvider::ScopedSamplerGL(resource_provider_,
    851                                               contents_texture->id(),
    852                                               GL_TEXTURE_2D,
    853                                               GL_LINEAR));
    854   }
    855 
    856   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
    857       context_, &highp_threshold_cache_, highp_threshold_min_,
    858       quad->shared_quad_state->visible_content_rect.bottom_right());
    859 
    860   int shader_quad_location = -1;
    861   int shader_edge_location = -1;
    862   int shader_viewport_location = -1;
    863   int shader_mask_sampler_location = -1;
    864   int shader_mask_tex_coord_scale_location = -1;
    865   int shader_mask_tex_coord_offset_location = -1;
    866   int shader_matrix_location = -1;
    867   int shader_alpha_location = -1;
    868   int shader_color_matrix_location = -1;
    869   int shader_color_offset_location = -1;
    870   int shader_tex_transform_location = -1;
    871 
    872   if (use_aa && mask_texture_id && !use_color_matrix) {
    873     const RenderPassMaskProgramAA* program =
    874         GetRenderPassMaskProgramAA(tex_coord_precision);
    875     SetUseProgram(program->program());
    876     GLC(Context(),
    877         Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
    878 
    879     shader_quad_location = program->vertex_shader().quad_location();
    880     shader_edge_location = program->vertex_shader().edge_location();
    881     shader_viewport_location = program->vertex_shader().viewport_location();
    882     shader_mask_sampler_location =
    883         program->fragment_shader().mask_sampler_location();
    884     shader_mask_tex_coord_scale_location =
    885         program->fragment_shader().mask_tex_coord_scale_location();
    886     shader_mask_tex_coord_offset_location =
    887         program->fragment_shader().mask_tex_coord_offset_location();
    888     shader_matrix_location = program->vertex_shader().matrix_location();
    889     shader_alpha_location = program->fragment_shader().alpha_location();
    890     shader_tex_transform_location =
    891         program->vertex_shader().tex_transform_location();
    892   } else if (!use_aa && mask_texture_id && !use_color_matrix) {
    893     const RenderPassMaskProgram* program =
    894         GetRenderPassMaskProgram(tex_coord_precision);
    895     SetUseProgram(program->program());
    896     GLC(Context(),
    897         Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
    898 
    899     shader_mask_sampler_location =
    900         program->fragment_shader().mask_sampler_location();
    901     shader_mask_tex_coord_scale_location =
    902         program->fragment_shader().mask_tex_coord_scale_location();
    903     shader_mask_tex_coord_offset_location =
    904         program->fragment_shader().mask_tex_coord_offset_location();
    905     shader_matrix_location = program->vertex_shader().matrix_location();
    906     shader_alpha_location = program->fragment_shader().alpha_location();
    907     shader_tex_transform_location =
    908         program->vertex_shader().tex_transform_location();
    909   } else if (use_aa && !mask_texture_id && !use_color_matrix) {
    910     const RenderPassProgramAA* program =
    911         GetRenderPassProgramAA(tex_coord_precision);
    912     SetUseProgram(program->program());
    913     GLC(Context(),
    914         Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
    915 
    916     shader_quad_location = program->vertex_shader().quad_location();
    917     shader_edge_location = program->vertex_shader().edge_location();
    918     shader_viewport_location = program->vertex_shader().viewport_location();
    919     shader_matrix_location = program->vertex_shader().matrix_location();
    920     shader_alpha_location = program->fragment_shader().alpha_location();
    921     shader_tex_transform_location =
    922         program->vertex_shader().tex_transform_location();
    923   } else if (use_aa && mask_texture_id && use_color_matrix) {
    924     const RenderPassMaskColorMatrixProgramAA* program =
    925         GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision);
    926     SetUseProgram(program->program());
    927     GLC(Context(),
    928         Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
    929 
    930     shader_matrix_location = program->vertex_shader().matrix_location();
    931     shader_quad_location = program->vertex_shader().quad_location();
    932     shader_tex_transform_location =
    933         program->vertex_shader().tex_transform_location();
    934     shader_edge_location = program->vertex_shader().edge_location();
    935     shader_viewport_location = program->vertex_shader().viewport_location();
    936     shader_alpha_location = program->fragment_shader().alpha_location();
    937     shader_mask_sampler_location =
    938         program->fragment_shader().mask_sampler_location();
    939     shader_mask_tex_coord_scale_location =
    940         program->fragment_shader().mask_tex_coord_scale_location();
    941     shader_mask_tex_coord_offset_location =
    942         program->fragment_shader().mask_tex_coord_offset_location();
    943     shader_color_matrix_location =
    944         program->fragment_shader().color_matrix_location();
    945     shader_color_offset_location =
    946         program->fragment_shader().color_offset_location();
    947   } else if (use_aa && !mask_texture_id && use_color_matrix) {
    948     const RenderPassColorMatrixProgramAA* program =
    949         GetRenderPassColorMatrixProgramAA(tex_coord_precision);
    950     SetUseProgram(program->program());
    951     GLC(Context(),
    952         Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
    953 
    954     shader_matrix_location = program->vertex_shader().matrix_location();
    955     shader_quad_location = program->vertex_shader().quad_location();
    956     shader_tex_transform_location =
    957         program->vertex_shader().tex_transform_location();
    958     shader_edge_location = program->vertex_shader().edge_location();
    959     shader_viewport_location = program->vertex_shader().viewport_location();
    960     shader_alpha_location = program->fragment_shader().alpha_location();
    961     shader_color_matrix_location =
    962         program->fragment_shader().color_matrix_location();
    963     shader_color_offset_location =
    964         program->fragment_shader().color_offset_location();
    965   } else if (!use_aa && mask_texture_id && use_color_matrix) {
    966     const RenderPassMaskColorMatrixProgram* program =
    967         GetRenderPassMaskColorMatrixProgram(tex_coord_precision);
    968     SetUseProgram(program->program());
    969     GLC(Context(),
    970         Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
    971 
    972     shader_matrix_location = program->vertex_shader().matrix_location();
    973     shader_tex_transform_location =
    974         program->vertex_shader().tex_transform_location();
    975     shader_mask_sampler_location =
    976         program->fragment_shader().mask_sampler_location();
    977     shader_mask_tex_coord_scale_location =
    978         program->fragment_shader().mask_tex_coord_scale_location();
    979     shader_mask_tex_coord_offset_location =
    980         program->fragment_shader().mask_tex_coord_offset_location();
    981     shader_alpha_location = program->fragment_shader().alpha_location();
    982     shader_color_matrix_location =
    983         program->fragment_shader().color_matrix_location();
    984     shader_color_offset_location =
    985         program->fragment_shader().color_offset_location();
    986   } else if (!use_aa && !mask_texture_id && use_color_matrix) {
    987     const RenderPassColorMatrixProgram* program =
    988         GetRenderPassColorMatrixProgram(tex_coord_precision);
    989     SetUseProgram(program->program());
    990     GLC(Context(),
    991         Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
    992 
    993     shader_matrix_location = program->vertex_shader().matrix_location();
    994     shader_tex_transform_location =
    995         program->vertex_shader().tex_transform_location();
    996     shader_alpha_location = program->fragment_shader().alpha_location();
    997     shader_color_matrix_location =
    998         program->fragment_shader().color_matrix_location();
    999     shader_color_offset_location =
   1000         program->fragment_shader().color_offset_location();
   1001   } else {
   1002     const RenderPassProgram* program =
   1003         GetRenderPassProgram(tex_coord_precision);
   1004     SetUseProgram(program->program());
   1005     GLC(Context(),
   1006         Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
   1007 
   1008     shader_matrix_location = program->vertex_shader().matrix_location();
   1009     shader_alpha_location = program->fragment_shader().alpha_location();
   1010     shader_tex_transform_location =
   1011         program->vertex_shader().tex_transform_location();
   1012   }
   1013   float tex_scale_x =
   1014       quad->rect.width() / static_cast<float>(contents_texture->size().width());
   1015   float tex_scale_y = quad->rect.height() /
   1016                       static_cast<float>(contents_texture->size().height());
   1017   DCHECK_LE(tex_scale_x, 1.0f);
   1018   DCHECK_LE(tex_scale_y, 1.0f);
   1019 
   1020   DCHECK(shader_tex_transform_location != -1 || IsContextLost());
   1021   // Flip the content vertically in the shader, as the RenderPass input
   1022   // texture is already oriented the same way as the framebuffer, but the
   1023   // projection transform does a flip.
   1024   GLC(Context(), Context()->uniform4f(shader_tex_transform_location,
   1025                                       0.0f,
   1026                                       tex_scale_y,
   1027                                       tex_scale_x,
   1028                                       -tex_scale_y));
   1029 
   1030   scoped_ptr<ResourceProvider::ScopedReadLockGL> shader_mask_sampler_lock;
   1031   if (shader_mask_sampler_location != -1) {
   1032     DCHECK_NE(shader_mask_tex_coord_scale_location, 1);
   1033     DCHECK_NE(shader_mask_tex_coord_offset_location, 1);
   1034     GLC(Context(), Context()->uniform1i(shader_mask_sampler_location, 1));
   1035 
   1036     float mask_tex_scale_x = quad->mask_uv_rect.width() / tex_scale_x;
   1037     float mask_tex_scale_y = quad->mask_uv_rect.height() / tex_scale_y;
   1038 
   1039     // Mask textures are oriented vertically flipped relative to the framebuffer
   1040     // and the RenderPass contents texture, so we flip the tex coords from the
   1041     // RenderPass texture to find the mask texture coords.
   1042     GLC(Context(),
   1043         Context()->uniform2f(shader_mask_tex_coord_offset_location,
   1044                              quad->mask_uv_rect.x(),
   1045                              quad->mask_uv_rect.y() + mask_tex_scale_y));
   1046     GLC(Context(),
   1047         Context()->uniform2f(shader_mask_tex_coord_scale_location,
   1048                              mask_tex_scale_x,
   1049                              -mask_tex_scale_y));
   1050     shader_mask_sampler_lock = make_scoped_ptr(
   1051         new ResourceProvider::ScopedSamplerGL(resource_provider_,
   1052                                               quad->mask_resource_id,
   1053                                               GL_TEXTURE_2D,
   1054                                               GL_TEXTURE1,
   1055                                               GL_LINEAR));
   1056   }
   1057 
   1058   if (shader_edge_location != -1) {
   1059     float edge[24];
   1060     device_layer_edges.ToFloatArray(edge);
   1061     device_layer_bounds.ToFloatArray(&edge[12]);
   1062     GLC(Context(), Context()->uniform3fv(shader_edge_location, 8, edge));
   1063   }
   1064 
   1065   if (shader_viewport_location != -1) {
   1066     float viewport[4] = {
   1067       static_cast<float>(viewport_.x()),
   1068       static_cast<float>(viewport_.y()),
   1069       static_cast<float>(viewport_.width()),
   1070       static_cast<float>(viewport_.height()),
   1071     };
   1072     GLC(Context(),
   1073         Context()->uniform4fv(shader_viewport_location, 1, viewport));
   1074   }
   1075 
   1076   if (shader_color_matrix_location != -1) {
   1077     float matrix[16];
   1078     for (int i = 0; i < 4; ++i) {
   1079       for (int j = 0; j < 4; ++j)
   1080         matrix[i * 4 + j] = SkScalarToFloat(color_matrix[j * 5 + i]);
   1081     }
   1082     GLC(Context(),
   1083         Context()->uniformMatrix4fv(
   1084             shader_color_matrix_location, 1, false, matrix));
   1085   }
   1086   static const float kScale = 1.0f / 255.0f;
   1087   if (shader_color_offset_location != -1) {
   1088     float offset[4];
   1089     for (int i = 0; i < 4; ++i)
   1090       offset[i] = SkScalarToFloat(color_matrix[i * 5 + 4]) * kScale;
   1091 
   1092     GLC(Context(),
   1093         Context()->uniform4fv(shader_color_offset_location, 1, offset));
   1094   }
   1095 
   1096   // Map device space quad to surface space. contents_device_transform has no 3d
   1097   // component since it was flattened, so we don't need to project.
   1098   gfx::QuadF surface_quad = MathUtil::MapQuad(contents_device_transform_inverse,
   1099                                               device_layer_edges.ToQuadF(),
   1100                                               &clipped);
   1101 
   1102   SetShaderOpacity(quad->opacity(), shader_alpha_location);
   1103   SetShaderQuadF(surface_quad, shader_quad_location);
   1104   DrawQuadGeometry(
   1105       frame, quad->quadTransform(), quad->rect, shader_matrix_location);
   1106 
   1107   // Flush the compositor context before the filter bitmap goes out of
   1108   // scope, so the draw gets processed before the filter texture gets deleted.
   1109   if (filter_bitmap.getTexture())
   1110     context_->flush();
   1111 }
   1112 
   1113 struct SolidColorProgramUniforms {
   1114   unsigned program;
   1115   unsigned matrix_location;
   1116   unsigned viewport_location;
   1117   unsigned quad_location;
   1118   unsigned edge_location;
   1119   unsigned color_location;
   1120 };
   1121 
   1122 template<class T>
   1123 static void SolidColorUniformLocation(T program,
   1124                                       SolidColorProgramUniforms* uniforms) {
   1125   uniforms->program = program->program();
   1126   uniforms->matrix_location = program->vertex_shader().matrix_location();
   1127   uniforms->viewport_location = program->vertex_shader().viewport_location();
   1128   uniforms->quad_location = program->vertex_shader().quad_location();
   1129   uniforms->edge_location = program->vertex_shader().edge_location();
   1130   uniforms->color_location = program->fragment_shader().color_location();
   1131 }
   1132 
   1133 bool GLRenderer::SetupQuadForAntialiasing(
   1134     const gfx::Transform& device_transform,
   1135     const DrawQuad* quad,
   1136     gfx::QuadF* local_quad,
   1137     float edge[24]) const {
   1138   gfx::Rect tile_rect = quad->visible_rect;
   1139 
   1140   bool clipped = false;
   1141   gfx::QuadF device_layer_quad = MathUtil::MapQuad(
   1142       device_transform, gfx::QuadF(quad->visibleContentRect()), &clipped);
   1143 
   1144   bool is_axis_aligned_in_target = device_layer_quad.IsRectilinear();
   1145   bool is_nearest_rect_within_epsilon = is_axis_aligned_in_target &&
   1146       gfx::IsNearestRectWithinDistance(device_layer_quad.BoundingBox(),
   1147                                        kAntiAliasingEpsilon);
   1148 
   1149   bool use_aa = Settings().allow_antialiasing &&
   1150                 !clipped &&  // code can't handle clipped quads
   1151                 !is_nearest_rect_within_epsilon &&
   1152                 quad->IsEdge();
   1153   if (!use_aa)
   1154     return false;
   1155 
   1156   LayerQuad device_layer_bounds(gfx::QuadF(device_layer_quad.BoundingBox()));
   1157   device_layer_bounds.InflateAntiAliasingDistance();
   1158 
   1159   LayerQuad device_layer_edges(device_layer_quad);
   1160   device_layer_edges.InflateAntiAliasingDistance();
   1161 
   1162   device_layer_edges.ToFloatArray(edge);
   1163   device_layer_bounds.ToFloatArray(&edge[12]);
   1164 
   1165   gfx::PointF bottom_right = tile_rect.bottom_right();
   1166   gfx::PointF bottom_left = tile_rect.bottom_left();
   1167   gfx::PointF top_left = tile_rect.origin();
   1168   gfx::PointF top_right = tile_rect.top_right();
   1169 
   1170   // Map points to device space.
   1171   bottom_right = MathUtil::MapPoint(device_transform, bottom_right, &clipped);
   1172   DCHECK(!clipped);
   1173   bottom_left = MathUtil::MapPoint(device_transform, bottom_left, &clipped);
   1174   DCHECK(!clipped);
   1175   top_left = MathUtil::MapPoint(device_transform, top_left, &clipped);
   1176   DCHECK(!clipped);
   1177   top_right = MathUtil::MapPoint(device_transform, top_right, &clipped);
   1178   DCHECK(!clipped);
   1179 
   1180   LayerQuad::Edge bottom_edge(bottom_right, bottom_left);
   1181   LayerQuad::Edge left_edge(bottom_left, top_left);
   1182   LayerQuad::Edge top_edge(top_left, top_right);
   1183   LayerQuad::Edge right_edge(top_right, bottom_right);
   1184 
   1185   // Only apply anti-aliasing to edges not clipped by culling or scissoring.
   1186   if (quad->IsTopEdge() && tile_rect.y() == quad->rect.y())
   1187     top_edge = device_layer_edges.top();
   1188   if (quad->IsLeftEdge() && tile_rect.x() == quad->rect.x())
   1189     left_edge = device_layer_edges.left();
   1190   if (quad->IsRightEdge() && tile_rect.right() == quad->rect.right())
   1191     right_edge = device_layer_edges.right();
   1192   if (quad->IsBottomEdge() && tile_rect.bottom() == quad->rect.bottom())
   1193     bottom_edge = device_layer_edges.bottom();
   1194 
   1195   float sign = gfx::QuadF(tile_rect).IsCounterClockwise() ? -1 : 1;
   1196   bottom_edge.scale(sign);
   1197   left_edge.scale(sign);
   1198   top_edge.scale(sign);
   1199   right_edge.scale(sign);
   1200 
   1201   // Create device space quad.
   1202   LayerQuad device_quad(left_edge, top_edge, right_edge, bottom_edge);
   1203 
   1204   // Map device space quad to local space. device_transform has no 3d
   1205   // component since it was flattened, so we don't need to project.  We should
   1206   // have already checked that the transform was uninvertible above.
   1207   gfx::Transform inverse_device_transform(
   1208       gfx::Transform::kSkipInitialization);
   1209   bool did_invert = device_transform.GetInverse(&inverse_device_transform);
   1210   DCHECK(did_invert);
   1211   *local_quad = MathUtil::MapQuad(
   1212       inverse_device_transform, device_quad.ToQuadF(), &clipped);
   1213   // We should not DCHECK(!clipped) here, because anti-aliasing inflation may
   1214   // cause device_quad to become clipped. To our knowledge this scenario does
   1215   // not need to be handled differently than the unclipped case.
   1216 
   1217   return true;
   1218 }
   1219 
   1220 void GLRenderer::DrawSolidColorQuad(const DrawingFrame* frame,
   1221                                     const SolidColorDrawQuad* quad) {
   1222   gfx::Rect tile_rect = quad->visible_rect;
   1223 
   1224   SkColor color = quad->color;
   1225   float opacity = quad->opacity();
   1226   float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity;
   1227 
   1228   // Early out if alpha is small enough that quad doesn't contribute to output.
   1229   if (alpha < std::numeric_limits<float>::epsilon() &&
   1230       quad->ShouldDrawWithBlending())
   1231     return;
   1232 
   1233   gfx::Transform device_transform =
   1234       frame->window_matrix * frame->projection_matrix * quad->quadTransform();
   1235   device_transform.FlattenTo2d();
   1236   if (!device_transform.IsInvertible())
   1237     return;
   1238 
   1239   gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect));
   1240   float edge[24];
   1241   bool use_aa = !quad->force_anti_aliasing_off && SetupQuadForAntialiasing(
   1242       device_transform, quad, &local_quad, edge);
   1243 
   1244   SolidColorProgramUniforms uniforms;
   1245   if (use_aa)
   1246     SolidColorUniformLocation(GetSolidColorProgramAA(), &uniforms);
   1247   else
   1248     SolidColorUniformLocation(GetSolidColorProgram(), &uniforms);
   1249   SetUseProgram(uniforms.program);
   1250 
   1251   GLC(Context(),
   1252       Context()->uniform4f(uniforms.color_location,
   1253                            (SkColorGetR(color) * (1.0f / 255.0f)) * alpha,
   1254                            (SkColorGetG(color) * (1.0f / 255.0f)) * alpha,
   1255                            (SkColorGetB(color) * (1.0f / 255.0f)) * alpha,
   1256                            alpha));
   1257   if (use_aa) {
   1258     float viewport[4] = {
   1259       static_cast<float>(viewport_.x()),
   1260       static_cast<float>(viewport_.y()),
   1261       static_cast<float>(viewport_.width()),
   1262       static_cast<float>(viewport_.height()),
   1263     };
   1264     GLC(Context(),
   1265         Context()->uniform4fv(uniforms.viewport_location, 1, viewport));
   1266     GLC(Context(), Context()->uniform3fv(uniforms.edge_location, 8, edge));
   1267   }
   1268 
   1269   // Enable blending when the quad properties require it or if we decided
   1270   // to use antialiasing.
   1271   SetBlendEnabled(quad->ShouldDrawWithBlending() || use_aa);
   1272 
   1273   // Normalize to tile_rect.
   1274   local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height());
   1275 
   1276   SetShaderQuadF(local_quad, uniforms.quad_location);
   1277 
   1278   // The transform and vertex data are used to figure out the extents that the
   1279   // un-antialiased quad should have and which vertex this is and the float
   1280   // quad passed in via uniform is the actual geometry that gets used to draw
   1281   // it. This is why this centered rect is used and not the original quad_rect.
   1282   gfx::RectF centered_rect(gfx::PointF(-0.5f * tile_rect.width(),
   1283                                        -0.5f * tile_rect.height()),
   1284                            tile_rect.size());
   1285   DrawQuadGeometry(frame, quad->quadTransform(),
   1286                    centered_rect, uniforms.matrix_location);
   1287 }
   1288 
   1289 struct TileProgramUniforms {
   1290   unsigned program;
   1291   unsigned matrix_location;
   1292   unsigned viewport_location;
   1293   unsigned quad_location;
   1294   unsigned edge_location;
   1295   unsigned vertex_tex_transform_location;
   1296   unsigned sampler_location;
   1297   unsigned fragment_tex_transform_location;
   1298   unsigned alpha_location;
   1299 };
   1300 
   1301 template <class T>
   1302 static void TileUniformLocation(T program, TileProgramUniforms* uniforms) {
   1303   uniforms->program = program->program();
   1304   uniforms->matrix_location = program->vertex_shader().matrix_location();
   1305   uniforms->viewport_location = program->vertex_shader().viewport_location();
   1306   uniforms->quad_location = program->vertex_shader().quad_location();
   1307   uniforms->edge_location = program->vertex_shader().edge_location();
   1308   uniforms->vertex_tex_transform_location =
   1309       program->vertex_shader().vertex_tex_transform_location();
   1310 
   1311   uniforms->sampler_location = program->fragment_shader().sampler_location();
   1312   uniforms->alpha_location = program->fragment_shader().alpha_location();
   1313   uniforms->fragment_tex_transform_location =
   1314       program->fragment_shader().fragment_tex_transform_location();
   1315 }
   1316 
   1317 void GLRenderer::DrawTileQuad(const DrawingFrame* frame,
   1318                               const TileDrawQuad* quad) {
   1319   DrawContentQuad(frame, quad, quad->resource_id);
   1320 }
   1321 
   1322 void GLRenderer::DrawContentQuad(const DrawingFrame* frame,
   1323                                  const ContentDrawQuadBase* quad,
   1324                                  ResourceProvider::ResourceId resource_id) {
   1325   gfx::Rect tile_rect = quad->visible_rect;
   1326 
   1327   gfx::RectF tex_coord_rect = quad->tex_coord_rect;
   1328   float tex_to_geom_scale_x = quad->rect.width() / tex_coord_rect.width();
   1329   float tex_to_geom_scale_y = quad->rect.height() / tex_coord_rect.height();
   1330 
   1331   // tex_coord_rect corresponds to quad_rect, but quad_visible_rect may be
   1332   // smaller than quad_rect due to occlusion or clipping. Adjust
   1333   // tex_coord_rect to match.
   1334   gfx::Vector2d top_left_diff = tile_rect.origin() - quad->rect.origin();
   1335   gfx::Vector2d bottom_right_diff =
   1336       tile_rect.bottom_right() - quad->rect.bottom_right();
   1337   tex_coord_rect.Inset(top_left_diff.x() / tex_to_geom_scale_x,
   1338                        top_left_diff.y() / tex_to_geom_scale_y,
   1339                        -bottom_right_diff.x() / tex_to_geom_scale_x,
   1340                        -bottom_right_diff.y() / tex_to_geom_scale_y);
   1341 
   1342   gfx::RectF clamp_geom_rect(tile_rect);
   1343   gfx::RectF clamp_tex_rect(tex_coord_rect);
   1344   // Clamp texture coordinates to avoid sampling outside the layer
   1345   // by deflating the tile region half a texel or half a texel
   1346   // minus epsilon for one pixel layers. The resulting clamp region
   1347   // is mapped to the unit square by the vertex shader and mapped
   1348   // back to normalized texture coordinates by the fragment shader
   1349   // after being clamped to 0-1 range.
   1350   float tex_clamp_x = std::min(
   1351       0.5f, 0.5f * clamp_tex_rect.width() - kAntiAliasingEpsilon);
   1352   float tex_clamp_y = std::min(
   1353       0.5f, 0.5f * clamp_tex_rect.height() - kAntiAliasingEpsilon);
   1354   float geom_clamp_x = std::min(
   1355       tex_clamp_x * tex_to_geom_scale_x,
   1356       0.5f * clamp_geom_rect.width() - kAntiAliasingEpsilon);
   1357   float geom_clamp_y = std::min(
   1358       tex_clamp_y * tex_to_geom_scale_y,
   1359       0.5f * clamp_geom_rect.height() - kAntiAliasingEpsilon);
   1360   clamp_geom_rect.Inset(geom_clamp_x, geom_clamp_y, geom_clamp_x, geom_clamp_y);
   1361   clamp_tex_rect.Inset(tex_clamp_x, tex_clamp_y, tex_clamp_x, tex_clamp_y);
   1362 
   1363   // Map clamping rectangle to unit square.
   1364   float vertex_tex_translate_x = -clamp_geom_rect.x() / clamp_geom_rect.width();
   1365   float vertex_tex_translate_y =
   1366       -clamp_geom_rect.y() / clamp_geom_rect.height();
   1367   float vertex_tex_scale_x = tile_rect.width() / clamp_geom_rect.width();
   1368   float vertex_tex_scale_y = tile_rect.height() / clamp_geom_rect.height();
   1369 
   1370   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
   1371       context_, &highp_threshold_cache_, highp_threshold_min_,
   1372       quad->texture_size);
   1373 
   1374   // Map to normalized texture coordinates.
   1375   gfx::Size texture_size = quad->texture_size;
   1376   float fragment_tex_translate_x = clamp_tex_rect.x() / texture_size.width();
   1377   float fragment_tex_translate_y = clamp_tex_rect.y() / texture_size.height();
   1378   float fragment_tex_scale_x = clamp_tex_rect.width() / texture_size.width();
   1379   float fragment_tex_scale_y = clamp_tex_rect.height() / texture_size.height();
   1380 
   1381   gfx::Transform device_transform =
   1382       frame->window_matrix * frame->projection_matrix * quad->quadTransform();
   1383   device_transform.FlattenTo2d();
   1384   if (!device_transform.IsInvertible())
   1385     return;
   1386 
   1387   gfx::QuadF local_quad = gfx::QuadF(gfx::RectF(tile_rect));
   1388   float edge[24];
   1389   bool use_aa = SetupQuadForAntialiasing(
   1390       device_transform, quad, &local_quad, edge);
   1391 
   1392   TileProgramUniforms uniforms;
   1393   if (use_aa) {
   1394     if (quad->swizzle_contents) {
   1395       TileUniformLocation(GetTileProgramSwizzleAA(tex_coord_precision),
   1396                           &uniforms);
   1397     } else {
   1398       TileUniformLocation(GetTileProgramAA(tex_coord_precision), &uniforms);
   1399     }
   1400   } else {
   1401     if (quad->ShouldDrawWithBlending()) {
   1402       if (quad->swizzle_contents) {
   1403         TileUniformLocation(GetTileProgramSwizzle(tex_coord_precision),
   1404                             &uniforms);
   1405       } else {
   1406         TileUniformLocation(GetTileProgram(tex_coord_precision), &uniforms);
   1407       }
   1408     } else {
   1409       if (quad->swizzle_contents) {
   1410         TileUniformLocation(GetTileProgramSwizzleOpaque(tex_coord_precision),
   1411                             &uniforms);
   1412       } else {
   1413         TileUniformLocation(GetTileProgramOpaque(tex_coord_precision),
   1414                             &uniforms);
   1415       }
   1416     }
   1417   }
   1418 
   1419   SetUseProgram(uniforms.program);
   1420   GLC(Context(), Context()->uniform1i(uniforms.sampler_location, 0));
   1421   bool scaled = (tex_to_geom_scale_x != 1.f || tex_to_geom_scale_y != 1.f);
   1422   GLenum filter = (use_aa || scaled ||
   1423                    !quad->quadTransform().IsIdentityOrIntegerTranslation())
   1424                   ? GL_LINEAR
   1425                   : GL_NEAREST;
   1426   ResourceProvider::ScopedSamplerGL quad_resource_lock(
   1427       resource_provider_, resource_id, GL_TEXTURE_2D, filter);
   1428 
   1429   if (use_aa) {
   1430     float viewport[4] = {
   1431       static_cast<float>(viewport_.x()),
   1432       static_cast<float>(viewport_.y()),
   1433       static_cast<float>(viewport_.width()),
   1434       static_cast<float>(viewport_.height()),
   1435     };
   1436     GLC(Context(),
   1437         Context()->uniform4fv(uniforms.viewport_location, 1, viewport));
   1438     GLC(Context(), Context()->uniform3fv(uniforms.edge_location, 8, edge));
   1439 
   1440     GLC(Context(),
   1441         Context()->uniform4f(uniforms.vertex_tex_transform_location,
   1442                              vertex_tex_translate_x,
   1443                              vertex_tex_translate_y,
   1444                              vertex_tex_scale_x,
   1445                              vertex_tex_scale_y));
   1446     GLC(Context(),
   1447         Context()->uniform4f(uniforms.fragment_tex_transform_location,
   1448                              fragment_tex_translate_x,
   1449                              fragment_tex_translate_y,
   1450                              fragment_tex_scale_x,
   1451                              fragment_tex_scale_y));
   1452   } else {
   1453     // Move fragment shader transform to vertex shader. We can do this while
   1454     // still producing correct results as fragment_tex_transform_location
   1455     // should always be non-negative when tiles are transformed in a way
   1456     // that could result in sampling outside the layer.
   1457     vertex_tex_scale_x *= fragment_tex_scale_x;
   1458     vertex_tex_scale_y *= fragment_tex_scale_y;
   1459     vertex_tex_translate_x *= fragment_tex_scale_x;
   1460     vertex_tex_translate_y *= fragment_tex_scale_y;
   1461     vertex_tex_translate_x += fragment_tex_translate_x;
   1462     vertex_tex_translate_y += fragment_tex_translate_y;
   1463 
   1464     GLC(Context(),
   1465         Context()->uniform4f(uniforms.vertex_tex_transform_location,
   1466                              vertex_tex_translate_x,
   1467                              vertex_tex_translate_y,
   1468                              vertex_tex_scale_x,
   1469                              vertex_tex_scale_y));
   1470   }
   1471 
   1472   // Enable blending when the quad properties require it or if we decided
   1473   // to use antialiasing.
   1474   SetBlendEnabled(quad->ShouldDrawWithBlending() || use_aa);
   1475 
   1476   // Normalize to tile_rect.
   1477   local_quad.Scale(1.0f / tile_rect.width(), 1.0f / tile_rect.height());
   1478 
   1479   SetShaderOpacity(quad->opacity(), uniforms.alpha_location);
   1480   SetShaderQuadF(local_quad, uniforms.quad_location);
   1481 
   1482   // The transform and vertex data are used to figure out the extents that the
   1483   // un-antialiased quad should have and which vertex this is and the float
   1484   // quad passed in via uniform is the actual geometry that gets used to draw
   1485   // it. This is why this centered rect is used and not the original quad_rect.
   1486   gfx::RectF centered_rect(
   1487       gfx::PointF(-0.5f * tile_rect.width(), -0.5f * tile_rect.height()),
   1488       tile_rect.size());
   1489   DrawQuadGeometry(
   1490       frame, quad->quadTransform(), centered_rect, uniforms.matrix_location);
   1491 }
   1492 
   1493 void GLRenderer::DrawYUVVideoQuad(const DrawingFrame* frame,
   1494                                   const YUVVideoDrawQuad* quad) {
   1495   SetBlendEnabled(quad->ShouldDrawWithBlending());
   1496 
   1497   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
   1498       context_, &highp_threshold_cache_, highp_threshold_min_,
   1499       quad->shared_quad_state->visible_content_rect.bottom_right());
   1500 
   1501   bool use_alpha_plane = quad->a_plane_resource_id != 0;
   1502 
   1503   ResourceProvider::ScopedSamplerGL y_plane_lock(
   1504       resource_provider_,
   1505       quad->y_plane_resource_id,
   1506       GL_TEXTURE_2D,
   1507       GL_TEXTURE1,
   1508       GL_LINEAR);
   1509   ResourceProvider::ScopedSamplerGL u_plane_lock(
   1510       resource_provider_,
   1511       quad->u_plane_resource_id,
   1512       GL_TEXTURE_2D,
   1513       GL_TEXTURE2,
   1514       GL_LINEAR);
   1515   ResourceProvider::ScopedSamplerGL v_plane_lock(
   1516       resource_provider_,
   1517       quad->v_plane_resource_id,
   1518       GL_TEXTURE_2D,
   1519       GL_TEXTURE3,
   1520       GL_LINEAR);
   1521   scoped_ptr<ResourceProvider::ScopedSamplerGL> a_plane_lock;
   1522   if (use_alpha_plane) {
   1523     a_plane_lock.reset(new ResourceProvider::ScopedSamplerGL(
   1524         resource_provider_,
   1525         quad->a_plane_resource_id,
   1526         GL_TEXTURE_2D,
   1527         GL_TEXTURE4,
   1528         GL_LINEAR));
   1529   }
   1530 
   1531   int tex_scale_location = -1;
   1532   int matrix_location = -1;
   1533   int y_texture_location = -1;
   1534   int u_texture_location = -1;
   1535   int v_texture_location = -1;
   1536   int a_texture_location = -1;
   1537   int yuv_matrix_location = -1;
   1538   int yuv_adj_location = -1;
   1539   int alpha_location = -1;
   1540   if (use_alpha_plane) {
   1541     const VideoYUVAProgram* program = GetVideoYUVAProgram(tex_coord_precision);
   1542     DCHECK(program && (program->initialized() || IsContextLost()));
   1543     SetUseProgram(program->program());
   1544     tex_scale_location = program->vertex_shader().tex_scale_location();
   1545     matrix_location = program->vertex_shader().matrix_location();
   1546     y_texture_location = program->fragment_shader().y_texture_location();
   1547     u_texture_location = program->fragment_shader().u_texture_location();
   1548     v_texture_location = program->fragment_shader().v_texture_location();
   1549     a_texture_location = program->fragment_shader().a_texture_location();
   1550     yuv_matrix_location = program->fragment_shader().yuv_matrix_location();
   1551     yuv_adj_location = program->fragment_shader().yuv_adj_location();
   1552     alpha_location = program->fragment_shader().alpha_location();
   1553   } else {
   1554     const VideoYUVProgram* program = GetVideoYUVProgram(tex_coord_precision);
   1555     DCHECK(program && (program->initialized() || IsContextLost()));
   1556     SetUseProgram(program->program());
   1557     tex_scale_location = program->vertex_shader().tex_scale_location();
   1558     matrix_location = program->vertex_shader().matrix_location();
   1559     y_texture_location = program->fragment_shader().y_texture_location();
   1560     u_texture_location = program->fragment_shader().u_texture_location();
   1561     v_texture_location = program->fragment_shader().v_texture_location();
   1562     yuv_matrix_location = program->fragment_shader().yuv_matrix_location();
   1563     yuv_adj_location = program->fragment_shader().yuv_adj_location();
   1564     alpha_location = program->fragment_shader().alpha_location();
   1565   }
   1566 
   1567   GLC(Context(),
   1568       Context()->uniform2f(tex_scale_location,
   1569                            quad->tex_scale.width(),
   1570                            quad->tex_scale.height()));
   1571   GLC(Context(), Context()->uniform1i(y_texture_location, 1));
   1572   GLC(Context(), Context()->uniform1i(u_texture_location, 2));
   1573   GLC(Context(), Context()->uniform1i(v_texture_location, 3));
   1574   if (use_alpha_plane)
   1575     GLC(Context(), Context()->uniform1i(a_texture_location, 4));
   1576 
   1577   // These values are magic numbers that are used in the transformation from YUV
   1578   // to RGB color values.  They are taken from the following webpage:
   1579   // http://www.fourcc.org/fccyvrgb.php
   1580   float yuv_to_rgb[9] = {
   1581       1.164f, 1.164f, 1.164f,
   1582       0.0f, -.391f, 2.018f,
   1583       1.596f, -.813f, 0.0f,
   1584   };
   1585   GLC(Context(),
   1586       Context()->uniformMatrix3fv(yuv_matrix_location, 1, 0, yuv_to_rgb));
   1587 
   1588   // These values map to 16, 128, and 128 respectively, and are computed
   1589   // as a fraction over 256 (e.g. 16 / 256 = 0.0625).
   1590   // They are used in the YUV to RGBA conversion formula:
   1591   //   Y - 16   : Gives 16 values of head and footroom for overshooting
   1592   //   U - 128  : Turns unsigned U into signed U [-128,127]
   1593   //   V - 128  : Turns unsigned V into signed V [-128,127]
   1594   float yuv_adjust[3] = { -0.0625f, -0.5f, -0.5f, };
   1595   GLC(Context(), Context()->uniform3fv(yuv_adj_location, 1, yuv_adjust));
   1596 
   1597 
   1598   SetShaderOpacity(quad->opacity(), alpha_location);
   1599   DrawQuadGeometry(frame, quad->quadTransform(), quad->rect, matrix_location);
   1600 }
   1601 
   1602 void GLRenderer::DrawStreamVideoQuad(const DrawingFrame* frame,
   1603                                      const StreamVideoDrawQuad* quad) {
   1604   SetBlendEnabled(quad->ShouldDrawWithBlending());
   1605 
   1606   static float gl_matrix[16];
   1607 
   1608   DCHECK(capabilities_.using_egl_image);
   1609 
   1610   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
   1611       context_, &highp_threshold_cache_, highp_threshold_min_,
   1612       quad->shared_quad_state->visible_content_rect.bottom_right());
   1613 
   1614   const VideoStreamTextureProgram* program =
   1615       GetVideoStreamTextureProgram(tex_coord_precision);
   1616   SetUseProgram(program->program());
   1617 
   1618   ToGLMatrix(&gl_matrix[0], quad->matrix);
   1619   GLC(Context(),
   1620       Context()->uniformMatrix4fv(
   1621           program->vertex_shader().tex_matrix_location(), 1, false, gl_matrix));
   1622 
   1623   ResourceProvider::ScopedReadLockGL lock(resource_provider_,
   1624                                           quad->resource_id);
   1625   DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
   1626   GLC(Context(),
   1627       Context()->bindTexture(GL_TEXTURE_EXTERNAL_OES, lock.texture_id()));
   1628 
   1629   GLC(Context(),
   1630       Context()->uniform1i(program->fragment_shader().sampler_location(), 0));
   1631 
   1632   SetShaderOpacity(quad->opacity(),
   1633                    program->fragment_shader().alpha_location());
   1634   DrawQuadGeometry(frame,
   1635                    quad->quadTransform(),
   1636                    quad->rect,
   1637                    program->vertex_shader().matrix_location());
   1638 }
   1639 
   1640 void GLRenderer::DrawPictureQuadDirectToBackbuffer(
   1641     const DrawingFrame* frame,
   1642     const PictureDrawQuad* quad) {
   1643   DCHECK(CanUseSkiaGPUBackend());
   1644   DCHECK_EQ(quad->opacity(), 1.f) << "Need to composite to a bitmap or a "
   1645                                      "render surface for non-1 opacity quads";
   1646 
   1647   // TODO(enne): This should be done more lazily / efficiently.
   1648   gr_context_->resetContext();
   1649 
   1650   // Reset the canvas matrix to identity because the clip rect is in target
   1651   // space.
   1652   SkMatrix sk_identity;
   1653   sk_identity.setIdentity();
   1654   sk_canvas_->setMatrix(sk_identity);
   1655 
   1656   if (is_scissor_enabled_) {
   1657     sk_canvas_->clipRect(gfx::RectToSkRect(scissor_rect_),
   1658                          SkRegion::kReplace_Op);
   1659   } else {
   1660     sk_canvas_->clipRect(gfx::RectToSkRect(client_->DeviceViewport()),
   1661                          SkRegion::kReplace_Op);
   1662   }
   1663 
   1664   gfx::Transform contents_device_transform = frame->window_matrix *
   1665     frame->projection_matrix * quad->quadTransform();
   1666   contents_device_transform.Translate(quad->rect.x(),
   1667                                       quad->rect.y());
   1668   contents_device_transform.FlattenTo2d();
   1669   SkMatrix sk_device_matrix;
   1670   gfx::TransformToFlattenedSkMatrix(contents_device_transform,
   1671                                     &sk_device_matrix);
   1672   sk_canvas_->setMatrix(sk_device_matrix);
   1673 
   1674   quad->picture_pile->RasterDirect(
   1675       sk_canvas_.get(), quad->content_rect, quad->contents_scale, NULL);
   1676 
   1677   // Flush any drawing buffers that have been deferred.
   1678   sk_canvas_->flush();
   1679 
   1680   // TODO(enne): This should be done more lazily / efficiently.
   1681   ReinitializeGLState();
   1682 }
   1683 
   1684 void GLRenderer::DrawPictureQuad(const DrawingFrame* frame,
   1685                                  const PictureDrawQuad* quad) {
   1686   if (quad->can_draw_direct_to_backbuffer && CanUseSkiaGPUBackend()) {
   1687     DrawPictureQuadDirectToBackbuffer(frame, quad);
   1688     return;
   1689   }
   1690 
   1691   if (on_demand_tile_raster_bitmap_.width() != quad->texture_size.width() ||
   1692       on_demand_tile_raster_bitmap_.height() != quad->texture_size.height()) {
   1693     on_demand_tile_raster_bitmap_.setConfig(
   1694         SkBitmap::kARGB_8888_Config,
   1695         quad->texture_size.width(),
   1696         quad->texture_size.height());
   1697     on_demand_tile_raster_bitmap_.allocPixels();
   1698 
   1699     if (on_demand_tile_raster_resource_id_)
   1700       resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_);
   1701 
   1702     on_demand_tile_raster_resource_id_ = resource_provider_->CreateGLTexture(
   1703         quad->texture_size,
   1704         GL_RGBA,
   1705         GL_TEXTURE_POOL_UNMANAGED_CHROMIUM,
   1706         ResourceProvider::TextureUsageAny);
   1707   }
   1708 
   1709   SkDevice device(on_demand_tile_raster_bitmap_);
   1710   SkCanvas canvas(&device);
   1711 
   1712   quad->picture_pile->RasterToBitmap(&canvas, quad->content_rect,
   1713                                      quad->contents_scale, NULL);
   1714 
   1715   resource_provider_->SetPixels(
   1716       on_demand_tile_raster_resource_id_,
   1717       reinterpret_cast<uint8_t*>(on_demand_tile_raster_bitmap_.getPixels()),
   1718       gfx::Rect(quad->texture_size),
   1719       gfx::Rect(quad->texture_size),
   1720       gfx::Vector2d());
   1721 
   1722   DrawContentQuad(frame, quad, on_demand_tile_raster_resource_id_);
   1723 }
   1724 
   1725 struct TextureProgramBinding {
   1726   template <class Program>
   1727   void Set(Program* program, WebKit::WebGraphicsContext3D* context) {
   1728     DCHECK(program && (program->initialized() || context->isContextLost()));
   1729     program_id = program->program();
   1730     sampler_location = program->fragment_shader().sampler_location();
   1731     matrix_location = program->vertex_shader().matrix_location();
   1732     background_color_location =
   1733         program->fragment_shader().background_color_location();
   1734   }
   1735   int program_id;
   1736   int sampler_location;
   1737   int matrix_location;
   1738   int background_color_location;
   1739 };
   1740 
   1741 struct TexTransformTextureProgramBinding : TextureProgramBinding {
   1742   template <class Program>
   1743   void Set(Program* program, WebKit::WebGraphicsContext3D* context) {
   1744     TextureProgramBinding::Set(program, context);
   1745     tex_transform_location = program->vertex_shader().tex_transform_location();
   1746     vertex_opacity_location =
   1747         program->vertex_shader().vertex_opacity_location();
   1748   }
   1749   int tex_transform_location;
   1750   int vertex_opacity_location;
   1751 };
   1752 
   1753 void GLRenderer::FlushTextureQuadCache() {
   1754   // Check to see if we have anything to draw.
   1755   if (draw_cache_.program_id == 0)
   1756     return;
   1757 
   1758   // Set the correct blending mode.
   1759   SetBlendEnabled(draw_cache_.needs_blending);
   1760 
   1761   // Bind the program to the GL state.
   1762   SetUseProgram(draw_cache_.program_id);
   1763 
   1764   // Bind the correct texture sampler location.
   1765   GLC(Context(), Context()->uniform1i(draw_cache_.sampler_location, 0));
   1766 
   1767   // Assume the current active textures is 0.
   1768   ResourceProvider::ScopedReadLockGL locked_quad(resource_provider_,
   1769                                                  draw_cache_.resource_id);
   1770   DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
   1771   GLC(Context(),
   1772       Context()->bindTexture(GL_TEXTURE_2D, locked_quad.texture_id()));
   1773 
   1774   COMPILE_ASSERT(
   1775       sizeof(Float4) == 4 * sizeof(float),  // NOLINT(runtime/sizeof)
   1776       struct_is_densely_packed);
   1777   COMPILE_ASSERT(
   1778       sizeof(Float16) == 16 * sizeof(float),  // NOLINT(runtime/sizeof)
   1779       struct_is_densely_packed);
   1780 
   1781   // Upload the tranforms for both points and uvs.
   1782   GLC(context_,
   1783       context_->uniformMatrix4fv(
   1784           static_cast<int>(draw_cache_.matrix_location),
   1785           static_cast<int>(draw_cache_.matrix_data.size()),
   1786           false,
   1787           reinterpret_cast<float*>(&draw_cache_.matrix_data.front())));
   1788   GLC(context_,
   1789       context_->uniform4fv(
   1790           static_cast<int>(draw_cache_.uv_xform_location),
   1791           static_cast<int>(draw_cache_.uv_xform_data.size()),
   1792           reinterpret_cast<float*>(&draw_cache_.uv_xform_data.front())));
   1793 
   1794   if (draw_cache_.background_color != SK_ColorTRANSPARENT) {
   1795     Float4 background_color = PremultipliedColor(draw_cache_.background_color);
   1796     GLC(context_,
   1797         context_->uniform4fv(
   1798             draw_cache_.background_color_location, 1, background_color.data));
   1799   }
   1800 
   1801   GLC(context_,
   1802       context_->uniform1fv(
   1803           static_cast<int>(draw_cache_.vertex_opacity_location),
   1804           static_cast<int>(draw_cache_.vertex_opacity_data.size()),
   1805           static_cast<float*>(&draw_cache_.vertex_opacity_data.front())));
   1806 
   1807   // Draw the quads!
   1808   GLC(context_,
   1809       context_->drawElements(GL_TRIANGLES,
   1810                              6 * draw_cache_.matrix_data.size(),
   1811                              GL_UNSIGNED_SHORT,
   1812                              0));
   1813 
   1814   // Clear the cache.
   1815   draw_cache_.program_id = 0;
   1816   draw_cache_.uv_xform_data.resize(0);
   1817   draw_cache_.vertex_opacity_data.resize(0);
   1818   draw_cache_.matrix_data.resize(0);
   1819 }
   1820 
   1821 void GLRenderer::EnqueueTextureQuad(const DrawingFrame* frame,
   1822                                     const TextureDrawQuad* quad) {
   1823   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
   1824       context_, &highp_threshold_cache_, highp_threshold_min_,
   1825       quad->shared_quad_state->visible_content_rect.bottom_right());
   1826 
   1827   // Choose the correct texture program binding
   1828   TexTransformTextureProgramBinding binding;
   1829   if (quad->premultiplied_alpha) {
   1830     if (quad->background_color == SK_ColorTRANSPARENT) {
   1831       binding.Set(GetTextureProgram(tex_coord_precision), Context());
   1832     } else {
   1833       binding.Set(GetTextureBackgroundProgram(tex_coord_precision), Context());
   1834     }
   1835   } else {
   1836     if (quad->background_color == SK_ColorTRANSPARENT) {
   1837       binding.Set(GetNonPremultipliedTextureProgram(tex_coord_precision),
   1838                   Context());
   1839     } else {
   1840       binding.Set(
   1841           GetNonPremultipliedTextureBackgroundProgram(tex_coord_precision),
   1842           Context());
   1843     }
   1844   }
   1845 
   1846   int resource_id = quad->resource_id;
   1847 
   1848   if (draw_cache_.program_id != binding.program_id ||
   1849       draw_cache_.resource_id != resource_id ||
   1850       draw_cache_.needs_blending != quad->ShouldDrawWithBlending() ||
   1851       draw_cache_.background_color != quad->background_color ||
   1852       draw_cache_.matrix_data.size() >= 8) {
   1853     FlushTextureQuadCache();
   1854     draw_cache_.program_id = binding.program_id;
   1855     draw_cache_.resource_id = resource_id;
   1856     draw_cache_.needs_blending = quad->ShouldDrawWithBlending();
   1857     draw_cache_.background_color = quad->background_color;
   1858 
   1859     draw_cache_.uv_xform_location = binding.tex_transform_location;
   1860     draw_cache_.background_color_location = binding.background_color_location;
   1861     draw_cache_.vertex_opacity_location = binding.vertex_opacity_location;
   1862     draw_cache_.matrix_location = binding.matrix_location;
   1863     draw_cache_.sampler_location = binding.sampler_location;
   1864   }
   1865 
   1866   // Generate the uv-transform
   1867   draw_cache_.uv_xform_data.push_back(UVTransform(quad));
   1868 
   1869   // Generate the vertex opacity
   1870   const float opacity = quad->opacity();
   1871   draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[0] * opacity);
   1872   draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[1] * opacity);
   1873   draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[2] * opacity);
   1874   draw_cache_.vertex_opacity_data.push_back(quad->vertex_opacity[3] * opacity);
   1875 
   1876   // Generate the transform matrix
   1877   gfx::Transform quad_rect_matrix;
   1878   QuadRectTransform(&quad_rect_matrix, quad->quadTransform(), quad->rect);
   1879   quad_rect_matrix = frame->projection_matrix * quad_rect_matrix;
   1880 
   1881   Float16 m;
   1882   quad_rect_matrix.matrix().asColMajorf(m.data);
   1883   draw_cache_.matrix_data.push_back(m);
   1884 }
   1885 
   1886 void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame* frame,
   1887                                    const IOSurfaceDrawQuad* quad) {
   1888   SetBlendEnabled(quad->ShouldDrawWithBlending());
   1889 
   1890   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
   1891       context_,  &highp_threshold_cache_, highp_threshold_min_,
   1892       quad->shared_quad_state->visible_content_rect.bottom_right());
   1893 
   1894   TexTransformTextureProgramBinding binding;
   1895   binding.Set(GetTextureIOSurfaceProgram(tex_coord_precision), Context());
   1896 
   1897   SetUseProgram(binding.program_id);
   1898   GLC(Context(), Context()->uniform1i(binding.sampler_location, 0));
   1899   if (quad->orientation == IOSurfaceDrawQuad::FLIPPED) {
   1900     GLC(Context(),
   1901         Context()->uniform4f(binding.tex_transform_location,
   1902                              0,
   1903                              quad->io_surface_size.height(),
   1904                              quad->io_surface_size.width(),
   1905                              quad->io_surface_size.height() * -1.0f));
   1906   } else {
   1907     GLC(Context(),
   1908         Context()->uniform4f(binding.tex_transform_location,
   1909                              0,
   1910                              0,
   1911                              quad->io_surface_size.width(),
   1912                              quad->io_surface_size.height()));
   1913   }
   1914 
   1915   const float vertex_opacity[] = { quad->opacity(), quad->opacity(),
   1916                                    quad->opacity(), quad->opacity() };
   1917   GLC(Context(),
   1918       Context()->uniform1fv(
   1919           binding.vertex_opacity_location, 4, vertex_opacity));
   1920 
   1921   ResourceProvider::ScopedReadLockGL lock(resource_provider_,
   1922                                           quad->io_surface_resource_id);
   1923   DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
   1924   GLC(Context(),
   1925       Context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB,
   1926                              lock.texture_id()));
   1927 
   1928   DrawQuadGeometry(
   1929       frame, quad->quadTransform(), quad->rect, binding.matrix_location);
   1930 
   1931   GLC(Context(), Context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB, 0));
   1932 }
   1933 
   1934 void GLRenderer::FinishDrawingFrame(DrawingFrame* frame) {
   1935   current_framebuffer_lock_.reset();
   1936   swap_buffer_rect_.Union(gfx::ToEnclosingRect(frame->root_damage_rect));
   1937 
   1938   GLC(context_, context_->disable(GL_BLEND));
   1939   blend_shadow_ = false;
   1940 }
   1941 
   1942 void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(); }
   1943 
   1944 bool GLRenderer::FlippedFramebuffer() const { return true; }
   1945 
   1946 void GLRenderer::EnsureScissorTestEnabled() {
   1947   if (is_scissor_enabled_)
   1948     return;
   1949 
   1950   FlushTextureQuadCache();
   1951   GLC(context_, context_->enable(GL_SCISSOR_TEST));
   1952   is_scissor_enabled_ = true;
   1953 }
   1954 
   1955 void GLRenderer::EnsureScissorTestDisabled() {
   1956   if (!is_scissor_enabled_)
   1957     return;
   1958 
   1959   FlushTextureQuadCache();
   1960   GLC(context_, context_->disable(GL_SCISSOR_TEST));
   1961   is_scissor_enabled_ = false;
   1962 }
   1963 
   1964 void GLRenderer::CopyCurrentRenderPassToBitmap(
   1965     DrawingFrame* frame,
   1966     scoped_ptr<CopyOutputRequest> request) {
   1967   gfx::Rect copy_rect = frame->current_render_pass->output_rect;
   1968   if (request->has_area()) {
   1969     // Intersect with the request's area, positioned with its origin at the
   1970     // origin of the full copy_rect.
   1971     copy_rect.Intersect(request->area() - copy_rect.OffsetFromOrigin());
   1972   }
   1973   GetFramebufferPixelsAsync(copy_rect, request.Pass());
   1974 }
   1975 
   1976 void GLRenderer::ToGLMatrix(float* gl_matrix, const gfx::Transform& transform) {
   1977   transform.matrix().asColMajorf(gl_matrix);
   1978 }
   1979 
   1980 void GLRenderer::SetShaderQuadF(const gfx::QuadF& quad, int quad_location) {
   1981   if (quad_location == -1)
   1982     return;
   1983 
   1984   float gl_quad[8];
   1985   gl_quad[0] = quad.p1().x();
   1986   gl_quad[1] = quad.p1().y();
   1987   gl_quad[2] = quad.p2().x();
   1988   gl_quad[3] = quad.p2().y();
   1989   gl_quad[4] = quad.p3().x();
   1990   gl_quad[5] = quad.p3().y();
   1991   gl_quad[6] = quad.p4().x();
   1992   gl_quad[7] = quad.p4().y();
   1993   GLC(context_, context_->uniform2fv(quad_location, 4, gl_quad));
   1994 }
   1995 
   1996 void GLRenderer::SetShaderOpacity(float opacity, int alpha_location) {
   1997   if (alpha_location != -1)
   1998     GLC(context_, context_->uniform1f(alpha_location, opacity));
   1999 }
   2000 
   2001 void GLRenderer::SetStencilEnabled(bool enabled) {
   2002   if (enabled == stencil_shadow_)
   2003     return;
   2004 
   2005   if (enabled)
   2006     GLC(context_, context_->enable(GL_STENCIL_TEST));
   2007   else
   2008     GLC(context_, context_->disable(GL_STENCIL_TEST));
   2009   stencil_shadow_ = enabled;
   2010 }
   2011 
   2012 void GLRenderer::SetBlendEnabled(bool enabled) {
   2013   if (enabled == blend_shadow_)
   2014     return;
   2015 
   2016   if (enabled)
   2017     GLC(context_, context_->enable(GL_BLEND));
   2018   else
   2019     GLC(context_, context_->disable(GL_BLEND));
   2020   blend_shadow_ = enabled;
   2021 }
   2022 
   2023 void GLRenderer::SetUseProgram(unsigned program) {
   2024   if (program == program_shadow_)
   2025     return;
   2026   GLC(context_, context_->useProgram(program));
   2027   program_shadow_ = program;
   2028 }
   2029 
   2030 void GLRenderer::DrawQuadGeometry(const DrawingFrame* frame,
   2031                                   const gfx::Transform& draw_transform,
   2032                                   const gfx::RectF& quad_rect,
   2033                                   int matrix_location) {
   2034   gfx::Transform quad_rect_matrix;
   2035   QuadRectTransform(&quad_rect_matrix, draw_transform, quad_rect);
   2036   static float gl_matrix[16];
   2037   ToGLMatrix(&gl_matrix[0], frame->projection_matrix * quad_rect_matrix);
   2038   GLC(context_,
   2039       context_->uniformMatrix4fv(matrix_location, 1, false, &gl_matrix[0]));
   2040 
   2041   GLC(context_, context_->drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0));
   2042 }
   2043 
   2044 void GLRenderer::CopyTextureToFramebuffer(const DrawingFrame* frame,
   2045                                           int texture_id,
   2046                                           gfx::Rect rect,
   2047                                           const gfx::Transform& draw_matrix,
   2048                                           bool flip_vertically) {
   2049   TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired(
   2050       context_, &highp_threshold_cache_, highp_threshold_min_,
   2051       rect.bottom_right());
   2052 
   2053   const RenderPassProgram* program = GetRenderPassProgram(tex_coord_precision);
   2054   SetUseProgram(program->program());
   2055 
   2056   GLC(Context(), Context()->uniform1i(
   2057       program->fragment_shader().sampler_location(), 0));
   2058 
   2059   if (flip_vertically) {
   2060     GLC(Context(), Context()->uniform4f(
   2061         program->vertex_shader().tex_transform_location(),
   2062         0.f,
   2063         1.f,
   2064         1.f,
   2065         -1.f));
   2066   } else {
   2067     GLC(Context(), Context()->uniform4f(
   2068         program->vertex_shader().tex_transform_location(),
   2069         0.f,
   2070         0.f,
   2071         1.f,
   2072         1.f));
   2073   }
   2074 
   2075   SetShaderOpacity(1.f, program->fragment_shader().alpha_location());
   2076   DCHECK_EQ(GL_TEXTURE0, ResourceProvider::GetActiveTextureUnit(Context()));
   2077   GLC(Context(), Context()->bindTexture(GL_TEXTURE_2D, texture_id));
   2078   DrawQuadGeometry(
   2079       frame, draw_matrix, rect, program->vertex_shader().matrix_location());
   2080 }
   2081 
   2082 void GLRenderer::Finish() {
   2083   TRACE_EVENT0("cc", "GLRenderer::finish");
   2084   context_->finish();
   2085 }
   2086 
   2087 void GLRenderer::SwapBuffers() {
   2088   DCHECK(visible_);
   2089   DCHECK(!is_backbuffer_discarded_);
   2090 
   2091   TRACE_EVENT0("cc", "GLRenderer::SwapBuffers");
   2092   // We're done! Time to swapbuffers!
   2093 
   2094   CompositorFrame compositor_frame;
   2095   compositor_frame.metadata = client_->MakeCompositorFrameMetadata();
   2096   compositor_frame.gl_frame_data = make_scoped_ptr(new GLFrameData);
   2097   compositor_frame.gl_frame_data->size = output_surface_->SurfaceSize();
   2098   if (capabilities_.using_partial_swap && client_->AllowPartialSwap()) {
   2099     // If supported, we can save significant bandwidth by only swapping the
   2100     // damaged/scissored region (clamped to the viewport)
   2101     swap_buffer_rect_.Intersect(client_->DeviceViewport());
   2102     int flipped_y_pos_of_rect_bottom =
   2103         client_->DeviceViewport().height() - swap_buffer_rect_.y() -
   2104         swap_buffer_rect_.height();
   2105     compositor_frame.gl_frame_data->sub_buffer_rect =
   2106         gfx::Rect(swap_buffer_rect_.x(),
   2107                   flipped_y_pos_of_rect_bottom,
   2108                   swap_buffer_rect_.width(),
   2109                   swap_buffer_rect_.height());
   2110   } else {
   2111     compositor_frame.gl_frame_data->sub_buffer_rect =
   2112         gfx::Rect(output_surface_->SurfaceSize());
   2113   }
   2114   output_surface_->SwapBuffers(&compositor_frame);
   2115 
   2116   swap_buffer_rect_ = gfx::Rect();
   2117 
   2118   // We don't have real fences, so we mark read fences as passed
   2119   // assuming a double-buffered GPU pipeline. A texture can be
   2120   // written to after one full frame has past since it was last read.
   2121   if (last_swap_fence_.get())
   2122     static_cast<SimpleSwapFence*>(last_swap_fence_.get())->SetHasPassed();
   2123   last_swap_fence_ = resource_provider_->GetReadLockFence();
   2124   resource_provider_->SetReadLockFence(new SimpleSwapFence());
   2125 }
   2126 
   2127 void GLRenderer::SetDiscardBackBufferWhenNotVisible(bool discard) {
   2128   discard_backbuffer_when_not_visible_ = discard;
   2129   EnforceMemoryPolicy();
   2130 }
   2131 
   2132 void GLRenderer::EnforceMemoryPolicy() {
   2133   if (!visible_) {
   2134     TRACE_EVENT0("cc", "GLRenderer::EnforceMemoryPolicy dropping resources");
   2135     ReleaseRenderPassTextures();
   2136     if (discard_backbuffer_when_not_visible_)
   2137       DiscardBackbuffer();
   2138     resource_provider_->ReleaseCachedData();
   2139     GLC(context_, context_->flush());
   2140   }
   2141 }
   2142 
   2143 void GLRenderer::DiscardBackbuffer() {
   2144   if (is_backbuffer_discarded_)
   2145     return;
   2146 
   2147   output_surface_->DiscardBackbuffer();
   2148 
   2149   is_backbuffer_discarded_ = true;
   2150 
   2151   // Damage tracker needs a full reset every time framebuffer is discarded.
   2152   client_->SetFullRootLayerDamage();
   2153 }
   2154 
   2155 void GLRenderer::EnsureBackbuffer() {
   2156   if (!is_backbuffer_discarded_)
   2157     return;
   2158 
   2159   output_surface_->EnsureBackbuffer();
   2160   is_backbuffer_discarded_ = false;
   2161 }
   2162 
   2163 void GLRenderer::GetFramebufferPixels(void* pixels, gfx::Rect rect) {
   2164   if (!pixels || rect.IsEmpty())
   2165     return;
   2166 
   2167   // This function assumes that it is reading the root frame buffer.
   2168   DCHECK(!current_framebuffer_lock_);
   2169 
   2170   scoped_ptr<PendingAsyncReadPixels> pending_read(new PendingAsyncReadPixels);
   2171   pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(),
   2172                                     pending_read.Pass());
   2173 
   2174   // This is a syncronous call since the callback is null.
   2175   gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect);
   2176   DoGetFramebufferPixels(static_cast<uint8*>(pixels),
   2177                          window_rect,
   2178                          AsyncGetFramebufferPixelsCleanupCallback());
   2179 }
   2180 
   2181 void GLRenderer::DeleteTextureReleaseCallbackOnImplThread(unsigned texture_id,
   2182                                                           unsigned sync_point,
   2183                                                           bool lost_resource) {
   2184   if (sync_point)
   2185     context_->waitSyncPoint(sync_point);
   2186   context_->deleteTexture(texture_id);
   2187 }
   2188 
   2189 // static
   2190 void GLRenderer::DeleteTextureReleaseCallback(
   2191     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
   2192     base::WeakPtr<GLRenderer> gl_renderer,
   2193     unsigned texture_id,
   2194     unsigned sync_point,
   2195     bool lost_resource) {
   2196   task_runner->PostTask(
   2197       FROM_HERE,
   2198       base::Bind(&GLRenderer::DeleteTextureReleaseCallbackOnImplThread,
   2199                  gl_renderer,
   2200                  texture_id,
   2201                  sync_point,
   2202                  lost_resource));
   2203 }
   2204 
   2205 void GLRenderer::GetFramebufferPixelsAsync(
   2206     gfx::Rect rect, scoped_ptr<CopyOutputRequest> request) {
   2207   DCHECK(!request->IsEmpty());
   2208   if (request->IsEmpty())
   2209     return;
   2210   if (rect.IsEmpty())
   2211     return;
   2212 
   2213   DCHECK(gfx::Rect(current_surface_size_).Contains(rect)) <<
   2214       "current_surface_size_: " << current_surface_size_.ToString() <<
   2215       " rect: " << rect.ToString();
   2216 
   2217   gfx::Rect window_rect = MoveFromDrawToWindowSpace(rect);
   2218 
   2219   if (!request->force_bitmap_result()) {
   2220     unsigned int texture_id = context_->createTexture();
   2221     GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
   2222     GLC(context_, context_->texParameteri(
   2223         GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
   2224     GLC(context_, context_->texParameteri(
   2225         GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
   2226     GLC(context_, context_->texParameteri(
   2227         GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
   2228     GLC(context_, context_->texParameteri(
   2229         GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
   2230     GetFramebufferTexture(texture_id, GL_RGBA, window_rect);
   2231 
   2232     gpu::Mailbox mailbox;
   2233     unsigned sync_point = 0;
   2234     GLC(context_, context_->genMailboxCHROMIUM(mailbox.name));
   2235     if (mailbox.IsZero()) {
   2236       context_->deleteTexture(texture_id);
   2237       request->SendEmptyResult();
   2238       return;
   2239     }
   2240 
   2241     GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
   2242     GLC(context_, context_->produceTextureCHROMIUM(
   2243         GL_TEXTURE_2D, mailbox.name));
   2244     GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0));
   2245     sync_point = context_->insertSyncPoint();
   2246     scoped_ptr<TextureMailbox> texture_mailbox = make_scoped_ptr(
   2247         new TextureMailbox(mailbox,
   2248                            base::Bind(&GLRenderer::DeleteTextureReleaseCallback,
   2249                                       base::MessageLoopProxy::current(),
   2250                                       weak_factory_.GetWeakPtr(),
   2251                                       texture_id),
   2252                            GL_TEXTURE_2D,
   2253                            sync_point));
   2254     request->SendTextureResult(window_rect.size(), texture_mailbox.Pass());
   2255     return;
   2256   }
   2257 
   2258   DCHECK(request->force_bitmap_result());
   2259 
   2260   scoped_ptr<SkBitmap> bitmap(new SkBitmap);
   2261   bitmap->setConfig(SkBitmap::kARGB_8888_Config,
   2262                     window_rect.width(),
   2263                     window_rect.height());
   2264   bitmap->allocPixels();
   2265 
   2266   scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap));
   2267 
   2268   // Save a pointer to the pixels, the bitmap is owned by the cleanup_callback.
   2269   uint8* pixels = static_cast<uint8*>(bitmap->getPixels());
   2270 
   2271   AsyncGetFramebufferPixelsCleanupCallback cleanup_callback = base::Bind(
   2272       &GLRenderer::PassOnSkBitmap,
   2273       base::Unretained(this),
   2274       base::Passed(&bitmap),
   2275       base::Passed(&lock));
   2276 
   2277   scoped_ptr<PendingAsyncReadPixels> pending_read(new PendingAsyncReadPixels);
   2278   pending_read->copy_request = request.Pass();
   2279   pending_async_read_pixels_.insert(pending_async_read_pixels_.begin(),
   2280                                     pending_read.Pass());
   2281 
   2282   // This is an asyncronous call since the callback is not null.
   2283   DoGetFramebufferPixels(pixels, window_rect, cleanup_callback);
   2284 }
   2285 
   2286 void GLRenderer::DoGetFramebufferPixels(
   2287     uint8* dest_pixels,
   2288     gfx::Rect window_rect,
   2289     const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback) {
   2290   DCHECK_GE(window_rect.x(), 0);
   2291   DCHECK_GE(window_rect.y(), 0);
   2292   DCHECK_LE(window_rect.right(), current_surface_size_.width());
   2293   DCHECK_LE(window_rect.bottom(), current_surface_size_.height());
   2294 
   2295   bool is_async = !cleanup_callback.is_null();
   2296 
   2297   MakeContextCurrent();
   2298 
   2299   bool do_workaround = NeedsIOSurfaceReadbackWorkaround();
   2300 
   2301   unsigned temporary_texture = 0;
   2302   unsigned temporary_fbo = 0;
   2303 
   2304   if (do_workaround) {
   2305     // On Mac OS X, calling glReadPixels() against an FBO whose color attachment
   2306     // is an IOSurface-backed texture causes corruption of future glReadPixels()
   2307     // calls, even those on different OpenGL contexts. It is believed that this
   2308     // is the root cause of top crasher
   2309     // http://crbug.com/99393. <rdar://problem/10949687>
   2310 
   2311     temporary_texture = context_->createTexture();
   2312     GLC(context_, context_->bindTexture(GL_TEXTURE_2D, temporary_texture));
   2313     GLC(context_, context_->texParameteri(
   2314         GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
   2315     GLC(context_, context_->texParameteri(
   2316         GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
   2317     GLC(context_, context_->texParameteri(
   2318         GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
   2319     GLC(context_, context_->texParameteri(
   2320         GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
   2321     // Copy the contents of the current (IOSurface-backed) framebuffer into a
   2322     // temporary texture.
   2323     GetFramebufferTexture(temporary_texture,
   2324                           GL_RGBA,
   2325                           gfx::Rect(current_surface_size_));
   2326     temporary_fbo = context_->createFramebuffer();
   2327     // Attach this texture to an FBO, and perform the readback from that FBO.
   2328     GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, temporary_fbo));
   2329     GLC(context_, context_->framebufferTexture2D(GL_FRAMEBUFFER,
   2330                                                  GL_COLOR_ATTACHMENT0,
   2331                                                  GL_TEXTURE_2D,
   2332                                                  temporary_texture,
   2333                                                  0));
   2334 
   2335     DCHECK_EQ(static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE),
   2336               context_->checkFramebufferStatus(GL_FRAMEBUFFER));
   2337   }
   2338 
   2339   unsigned buffer = context_->createBuffer();
   2340   GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
   2341                                      buffer));
   2342   GLC(context_, context_->bufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
   2343                                      4 * window_rect.size().GetArea(),
   2344                                      NULL,
   2345                                      GL_STREAM_READ));
   2346 
   2347   WebKit::WebGLId query = 0;
   2348   if (is_async) {
   2349     query = context_->createQueryEXT();
   2350     GLC(context_, context_->beginQueryEXT(
   2351         GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM,
   2352         query));
   2353   }
   2354 
   2355   GLC(context_,
   2356       context_->readPixels(window_rect.x(),
   2357                            window_rect.y(),
   2358                            window_rect.width(),
   2359                            window_rect.height(),
   2360                            GL_RGBA,
   2361                            GL_UNSIGNED_BYTE,
   2362                            NULL));
   2363 
   2364   GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
   2365                                      0));
   2366 
   2367   if (do_workaround) {
   2368     // Clean up.
   2369     GLC(context_, context_->bindFramebuffer(GL_FRAMEBUFFER, 0));
   2370     GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0));
   2371     GLC(context_, context_->deleteFramebuffer(temporary_fbo));
   2372     GLC(context_, context_->deleteTexture(temporary_texture));
   2373   }
   2374 
   2375   base::Closure finished_callback =
   2376       base::Bind(&GLRenderer::FinishedReadback,
   2377                  base::Unretained(this),
   2378                  cleanup_callback,
   2379                  buffer,
   2380                  query,
   2381                  dest_pixels,
   2382                  window_rect.size());
   2383   // Save the finished_callback so it can be cancelled.
   2384   pending_async_read_pixels_.front()->finished_read_pixels_callback.Reset(
   2385       finished_callback);
   2386 
   2387   // Save the buffer to verify the callbacks happen in the expected order.
   2388   pending_async_read_pixels_.front()->buffer = buffer;
   2389 
   2390   if (is_async) {
   2391     GLC(context_, context_->endQueryEXT(
   2392         GL_ASYNC_READ_PIXELS_COMPLETED_CHROMIUM));
   2393     SyncPointHelper::SignalQuery(
   2394         context_,
   2395         query,
   2396         finished_callback);
   2397   } else {
   2398     resource_provider_->Finish();
   2399     finished_callback.Run();
   2400   }
   2401 
   2402   EnforceMemoryPolicy();
   2403 }
   2404 
   2405 void GLRenderer::FinishedReadback(
   2406     const AsyncGetFramebufferPixelsCleanupCallback& cleanup_callback,
   2407     unsigned source_buffer,
   2408     unsigned query,
   2409     uint8* dest_pixels,
   2410     gfx::Size size) {
   2411   DCHECK(!pending_async_read_pixels_.empty());
   2412 
   2413   if (query != 0) {
   2414     GLC(context_, context_->deleteQueryEXT(query));
   2415   }
   2416 
   2417   PendingAsyncReadPixels* current_read = pending_async_read_pixels_.back();
   2418   // Make sure we service the readbacks in order.
   2419   DCHECK_EQ(source_buffer, current_read->buffer);
   2420 
   2421   uint8* src_pixels = NULL;
   2422 
   2423   if (source_buffer != 0) {
   2424     GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
   2425                                        source_buffer));
   2426     src_pixels = static_cast<uint8*>(
   2427         context_->mapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
   2428                                     GL_READ_ONLY));
   2429 
   2430     if (src_pixels) {
   2431       size_t row_bytes = size.width() * 4;
   2432       int num_rows = size.height();
   2433       size_t total_bytes = num_rows * row_bytes;
   2434       for (size_t dest_y = 0; dest_y < total_bytes; dest_y += row_bytes) {
   2435         // Flip Y axis.
   2436         size_t src_y = total_bytes - dest_y - row_bytes;
   2437         // Swizzle OpenGL -> Skia byte order.
   2438         for (size_t x = 0; x < row_bytes; x += 4) {
   2439           dest_pixels[dest_y + x + SK_R32_SHIFT/8] = src_pixels[src_y + x + 0];
   2440           dest_pixels[dest_y + x + SK_G32_SHIFT/8] = src_pixels[src_y + x + 1];
   2441           dest_pixels[dest_y + x + SK_B32_SHIFT/8] = src_pixels[src_y + x + 2];
   2442           dest_pixels[dest_y + x + SK_A32_SHIFT/8] = src_pixels[src_y + x + 3];
   2443         }
   2444       }
   2445 
   2446       GLC(context_, context_->unmapBufferCHROMIUM(
   2447           GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM));
   2448     }
   2449     GLC(context_, context_->bindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
   2450                                        0));
   2451     GLC(context_, context_->deleteBuffer(source_buffer));
   2452   }
   2453 
   2454   // TODO(danakj): This can go away when synchronous readback is no more and its
   2455   // contents can just move here.
   2456   if (!cleanup_callback.is_null())
   2457     cleanup_callback.Run(current_read->copy_request.Pass(), src_pixels != NULL);
   2458 
   2459   pending_async_read_pixels_.pop_back();
   2460 }
   2461 
   2462 void GLRenderer::PassOnSkBitmap(
   2463     scoped_ptr<SkBitmap> bitmap,
   2464     scoped_ptr<SkAutoLockPixels> lock,
   2465     scoped_ptr<CopyOutputRequest> request,
   2466     bool success) {
   2467   DCHECK(request->force_bitmap_result());
   2468 
   2469   lock.reset();
   2470   if (success)
   2471     request->SendBitmapResult(bitmap.Pass());
   2472 }
   2473 
   2474 void GLRenderer::GetFramebufferTexture(unsigned texture_id,
   2475                                        unsigned texture_format,
   2476                                        gfx::Rect window_rect) {
   2477   DCHECK(texture_id);
   2478   DCHECK_GE(window_rect.x(), 0);
   2479   DCHECK_GE(window_rect.y(), 0);
   2480   DCHECK_LE(window_rect.right(), current_surface_size_.width());
   2481   DCHECK_LE(window_rect.bottom(), current_surface_size_.height());
   2482 
   2483   GLC(context_, context_->bindTexture(GL_TEXTURE_2D, texture_id));
   2484   GLC(context_,
   2485       context_->copyTexImage2D(GL_TEXTURE_2D,
   2486                                0,
   2487                                texture_format,
   2488                                window_rect.x(),
   2489                                window_rect.y(),
   2490                                window_rect.width(),
   2491                                window_rect.height(),
   2492                                0));
   2493   GLC(context_, context_->bindTexture(GL_TEXTURE_2D, 0));
   2494 }
   2495 
   2496 bool GLRenderer::UseScopedTexture(DrawingFrame* frame,
   2497                                   const ScopedResource* texture,
   2498                                   gfx::Rect viewport_rect) {
   2499   DCHECK(texture->id());
   2500   frame->current_render_pass = NULL;
   2501   frame->current_texture = texture;
   2502 
   2503   return BindFramebufferToTexture(frame, texture, viewport_rect);
   2504 }
   2505 
   2506 void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame* frame) {
   2507   current_framebuffer_lock_.reset();
   2508   output_surface_->BindFramebuffer();
   2509 
   2510   if (client_->ExternalStencilTestEnabled()) {
   2511     SetStencilEnabled(true);
   2512     GLC(context_, context_->stencilFunc(GL_EQUAL, 1, 1));
   2513   } else {
   2514     SetStencilEnabled(false);
   2515   }
   2516 }
   2517 
   2518 bool GLRenderer::BindFramebufferToTexture(DrawingFrame* frame,
   2519                                           const ScopedResource* texture,
   2520                                           gfx::Rect target_rect) {
   2521   DCHECK(texture->id());
   2522 
   2523   current_framebuffer_lock_.reset();
   2524 
   2525   SetStencilEnabled(false);
   2526   GLC(context_,
   2527       context_->bindFramebuffer(GL_FRAMEBUFFER, offscreen_framebuffer_id_));
   2528   current_framebuffer_lock_ =
   2529       make_scoped_ptr(new ResourceProvider::ScopedWriteLockGL(
   2530           resource_provider_, texture->id()));
   2531   unsigned texture_id = current_framebuffer_lock_->texture_id();
   2532   GLC(context_,
   2533       context_->framebufferTexture2D(
   2534           GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0));
   2535 
   2536   DCHECK(context_->checkFramebufferStatus(GL_FRAMEBUFFER) ==
   2537          GL_FRAMEBUFFER_COMPLETE || IsContextLost());
   2538 
   2539   InitializeViewport(frame,
   2540                      target_rect,
   2541                      gfx::Rect(target_rect.size()),
   2542                      target_rect.size());
   2543   return true;
   2544 }
   2545 
   2546 void GLRenderer::SetScissorTestRect(gfx::Rect scissor_rect) {
   2547   EnsureScissorTestEnabled();
   2548 
   2549   // Don't unnecessarily ask the context to change the scissor, because it
   2550   // may cause undesired GPU pipeline flushes.
   2551   if (scissor_rect == scissor_rect_)
   2552     return;
   2553 
   2554   scissor_rect_ = scissor_rect;
   2555   FlushTextureQuadCache();
   2556   GLC(context_,
   2557       context_->scissor(scissor_rect.x(),
   2558                         scissor_rect.y(),
   2559                         scissor_rect.width(),
   2560                         scissor_rect.height()));
   2561 }
   2562 
   2563 void GLRenderer::SetDrawViewport(gfx::Rect window_space_viewport) {
   2564   viewport_ = window_space_viewport;
   2565   GLC(context_, context_->viewport(window_space_viewport.x(),
   2566                                    window_space_viewport.y(),
   2567                                    window_space_viewport.width(),
   2568                                    window_space_viewport.height()));
   2569 }
   2570 
   2571 bool GLRenderer::MakeContextCurrent() { return context_->makeContextCurrent(); }
   2572 
   2573 bool GLRenderer::InitializeSharedObjects() {
   2574   TRACE_EVENT0("cc", "GLRenderer::InitializeSharedObjects");
   2575   MakeContextCurrent();
   2576 
   2577   // Create an FBO for doing offscreen rendering.
   2578   GLC(context_, offscreen_framebuffer_id_ = context_->createFramebuffer());
   2579 
   2580   // We will always need these programs to render, so create the programs
   2581   // eagerly so that the shader compilation can start while we do other work.
   2582   // Other programs are created lazily on first access.
   2583   shared_geometry_ = make_scoped_ptr(
   2584       new GeometryBinding(context_, QuadVertexRect()));
   2585   render_pass_program_ = make_scoped_ptr(
   2586       new RenderPassProgram(context_, TexCoordPrecisionMedium));
   2587   render_pass_program_highp_ = make_scoped_ptr(
   2588       new RenderPassProgram(context_, TexCoordPrecisionHigh));
   2589   tile_program_ = make_scoped_ptr(
   2590       new TileProgram(context_, TexCoordPrecisionMedium));
   2591   tile_program_opaque_ = make_scoped_ptr(
   2592       new TileProgramOpaque(context_, TexCoordPrecisionMedium));
   2593   tile_program_highp_ = make_scoped_ptr(
   2594       new TileProgram(context_, TexCoordPrecisionHigh));
   2595   tile_program_opaque_highp_ = make_scoped_ptr(
   2596       new TileProgramOpaque(context_, TexCoordPrecisionHigh));
   2597 
   2598   GLC(context_, context_->flush());
   2599 
   2600   return true;
   2601 }
   2602 
   2603 const GLRenderer::TileCheckerboardProgram*
   2604 GLRenderer::GetTileCheckerboardProgram() {
   2605   if (!tile_checkerboard_program_)
   2606     tile_checkerboard_program_ = make_scoped_ptr(
   2607         new TileCheckerboardProgram(context_, TexCoordPrecisionNA));
   2608   if (!tile_checkerboard_program_->initialized()) {
   2609     TRACE_EVENT0("cc", "GLRenderer::checkerboardProgram::initalize");
   2610     tile_checkerboard_program_->Initialize(context_, is_using_bind_uniform_);
   2611   }
   2612   return tile_checkerboard_program_.get();
   2613 }
   2614 
   2615 const GLRenderer::DebugBorderProgram* GLRenderer::GetDebugBorderProgram() {
   2616   if (!debug_border_program_)
   2617     debug_border_program_ = make_scoped_ptr(
   2618         new DebugBorderProgram(context_, TexCoordPrecisionNA));
   2619   if (!debug_border_program_->initialized()) {
   2620     TRACE_EVENT0("cc", "GLRenderer::debugBorderProgram::initialize");
   2621     debug_border_program_->Initialize(context_, is_using_bind_uniform_);
   2622   }
   2623   return debug_border_program_.get();
   2624 }
   2625 
   2626 const GLRenderer::SolidColorProgram* GLRenderer::GetSolidColorProgram() {
   2627   if (!solid_color_program_)
   2628     solid_color_program_ = make_scoped_ptr(
   2629         new SolidColorProgram(context_, TexCoordPrecisionNA));
   2630   if (!solid_color_program_->initialized()) {
   2631     TRACE_EVENT0("cc", "GLRenderer::solidColorProgram::initialize");
   2632     solid_color_program_->Initialize(context_, is_using_bind_uniform_);
   2633   }
   2634   return solid_color_program_.get();
   2635 }
   2636 
   2637 const GLRenderer::SolidColorProgramAA* GLRenderer::GetSolidColorProgramAA() {
   2638   if (!solid_color_program_aa_) {
   2639     solid_color_program_aa_ =
   2640         make_scoped_ptr(new SolidColorProgramAA(context_, TexCoordPrecisionNA));
   2641   }
   2642   if (!solid_color_program_aa_->initialized()) {
   2643     TRACE_EVENT0("cc", "GLRenderer::solidColorProgramAA::initialize");
   2644     solid_color_program_aa_->Initialize(context_, is_using_bind_uniform_);
   2645   }
   2646   return solid_color_program_aa_.get();
   2647 }
   2648 
   2649 const GLRenderer::RenderPassProgram* GLRenderer::GetRenderPassProgram(
   2650       TexCoordPrecision precision) {
   2651   scoped_ptr<RenderPassProgram>& program =
   2652       (precision == TexCoordPrecisionHigh) ? render_pass_program_highp_
   2653                                            : render_pass_program_;
   2654   DCHECK(program);
   2655   if (!program->initialized()) {
   2656     TRACE_EVENT0("cc", "GLRenderer::renderPassProgram::initialize");
   2657     program->Initialize(context_, is_using_bind_uniform_);
   2658   }
   2659   return program.get();
   2660 }
   2661 
   2662 const GLRenderer::RenderPassProgramAA* GLRenderer::GetRenderPassProgramAA(
   2663       TexCoordPrecision precision) {
   2664   scoped_ptr<RenderPassProgramAA>& program =
   2665       (precision == TexCoordPrecisionHigh) ? render_pass_program_aa_highp_
   2666                                            : render_pass_program_aa_;
   2667   if (!program)
   2668     program =
   2669         make_scoped_ptr(new RenderPassProgramAA(context_, precision));
   2670   if (!program->initialized()) {
   2671     TRACE_EVENT0("cc", "GLRenderer::renderPassProgramAA::initialize");
   2672     program->Initialize(context_, is_using_bind_uniform_);
   2673   }
   2674   return program.get();
   2675 }
   2676 
   2677 const GLRenderer::RenderPassMaskProgram*
   2678 GLRenderer::GetRenderPassMaskProgram(TexCoordPrecision precision) {
   2679   scoped_ptr<RenderPassMaskProgram>& program =
   2680       (precision == TexCoordPrecisionHigh) ? render_pass_mask_program_highp_
   2681                                            : render_pass_mask_program_;
   2682   if (!program)
   2683     program = make_scoped_ptr(new RenderPassMaskProgram(context_, precision));
   2684   if (!program->initialized()) {
   2685     TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize");
   2686     program->Initialize(context_, is_using_bind_uniform_);
   2687   }
   2688   return program.get();
   2689 }
   2690 
   2691 const GLRenderer::RenderPassMaskProgramAA*
   2692 GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision) {
   2693   scoped_ptr<RenderPassMaskProgramAA>& program =
   2694       (precision == TexCoordPrecisionHigh) ? render_pass_mask_program_aa_highp_
   2695                                            : render_pass_mask_program_aa_;
   2696   if (!program)
   2697     program =
   2698         make_scoped_ptr(new RenderPassMaskProgramAA(context_, precision));
   2699   if (!program->initialized()) {
   2700     TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize");
   2701     program->Initialize(context_, is_using_bind_uniform_);
   2702   }
   2703   return program.get();
   2704 }
   2705 
   2706 const GLRenderer::RenderPassColorMatrixProgram*
   2707 GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision) {
   2708   scoped_ptr<RenderPassColorMatrixProgram>& program =
   2709       (precision == TexCoordPrecisionHigh) ?
   2710           render_pass_color_matrix_program_highp_ :
   2711           render_pass_color_matrix_program_;
   2712   if (!program)
   2713     program = make_scoped_ptr(
   2714         new RenderPassColorMatrixProgram(context_, precision));
   2715   if (!program->initialized()) {
   2716     TRACE_EVENT0("cc", "GLRenderer::renderPassColorMatrixProgram::initialize");
   2717     program->Initialize(context_, is_using_bind_uniform_);
   2718   }
   2719   return program.get();
   2720 }
   2721 
   2722 const GLRenderer::RenderPassColorMatrixProgramAA*
   2723 GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision) {
   2724   scoped_ptr<RenderPassColorMatrixProgramAA>& program =
   2725       (precision == TexCoordPrecisionHigh) ?
   2726           render_pass_color_matrix_program_aa_highp_ :
   2727           render_pass_color_matrix_program_aa_;
   2728   if (!program)
   2729     program = make_scoped_ptr(
   2730         new RenderPassColorMatrixProgramAA(context_, precision));
   2731   if (!program->initialized()) {
   2732     TRACE_EVENT0("cc",
   2733                  "GLRenderer::renderPassColorMatrixProgramAA::initialize");
   2734     program->Initialize(context_, is_using_bind_uniform_);
   2735   }
   2736   return program.get();
   2737 }
   2738 
   2739 const GLRenderer::RenderPassMaskColorMatrixProgram*
   2740 GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision) {
   2741   scoped_ptr<RenderPassMaskColorMatrixProgram>& program =
   2742       (precision == TexCoordPrecisionHigh) ?
   2743           render_pass_mask_color_matrix_program_highp_ :
   2744           render_pass_mask_color_matrix_program_;
   2745   if (!program)
   2746     program = make_scoped_ptr(
   2747         new RenderPassMaskColorMatrixProgram(context_, precision));
   2748   if (!program->initialized()) {
   2749     TRACE_EVENT0("cc",
   2750                  "GLRenderer::renderPassMaskColorMatrixProgram::initialize");
   2751     program->Initialize(context_, is_using_bind_uniform_);
   2752   }
   2753   return program.get();
   2754 }
   2755 
   2756 const GLRenderer::RenderPassMaskColorMatrixProgramAA*
   2757 GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision) {
   2758   scoped_ptr<RenderPassMaskColorMatrixProgramAA>& program =
   2759       (precision == TexCoordPrecisionHigh) ?
   2760           render_pass_mask_color_matrix_program_aa_highp_ :
   2761           render_pass_mask_color_matrix_program_aa_;
   2762   if (!program)
   2763     program = make_scoped_ptr(
   2764         new RenderPassMaskColorMatrixProgramAA(context_, precision));
   2765   if (!program->initialized()) {
   2766     TRACE_EVENT0("cc",
   2767                  "GLRenderer::renderPassMaskColorMatrixProgramAA::initialize");
   2768     program->Initialize(context_, is_using_bind_uniform_);
   2769   }
   2770   return program.get();
   2771 }
   2772 
   2773 const GLRenderer::TileProgram* GLRenderer::GetTileProgram(
   2774     TexCoordPrecision precision) {
   2775   scoped_ptr<TileProgram>& program =
   2776       (precision == TexCoordPrecisionHigh) ? tile_program_highp_
   2777                                            : tile_program_;
   2778   DCHECK(program);
   2779   if (!program->initialized()) {
   2780     TRACE_EVENT0("cc", "GLRenderer::tileProgram::initialize");
   2781     program->Initialize(context_, is_using_bind_uniform_);
   2782   }
   2783   return program.get();
   2784 }
   2785 
   2786 const GLRenderer::TileProgramOpaque* GLRenderer::GetTileProgramOpaque(
   2787     TexCoordPrecision precision) {
   2788   scoped_ptr<TileProgramOpaque>& program =
   2789       (precision == TexCoordPrecisionHigh) ? tile_program_opaque_highp_
   2790                                            : tile_program_opaque_;
   2791   DCHECK(program);
   2792   if (!program->initialized()) {
   2793     TRACE_EVENT0("cc", "GLRenderer::tileProgramOpaque::initialize");
   2794     program->Initialize(context_, is_using_bind_uniform_);
   2795   }
   2796   return program.get();
   2797 }
   2798 
   2799 const GLRenderer::TileProgramAA* GLRenderer::GetTileProgramAA(
   2800     TexCoordPrecision precision) {
   2801   scoped_ptr<TileProgramAA>& program =
   2802       (precision == TexCoordPrecisionHigh) ? tile_program_aa_highp_
   2803                                            : tile_program_aa_;
   2804   if (!program)
   2805     program = make_scoped_ptr(new TileProgramAA(context_, precision));
   2806   if (!program->initialized()) {
   2807     TRACE_EVENT0("cc", "GLRenderer::tileProgramAA::initialize");
   2808     program->Initialize(context_, is_using_bind_uniform_);
   2809   }
   2810   return program.get();
   2811 }
   2812 
   2813 const GLRenderer::TileProgramSwizzle* GLRenderer::GetTileProgramSwizzle(
   2814     TexCoordPrecision precision) {
   2815   scoped_ptr<TileProgramSwizzle>& program =
   2816       (precision == TexCoordPrecisionHigh) ? tile_program_swizzle_highp_
   2817                                            : tile_program_swizzle_;
   2818   if (!program)
   2819     program = make_scoped_ptr(new TileProgramSwizzle(context_, precision));
   2820   if (!program->initialized()) {
   2821     TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzle::initialize");
   2822     program->Initialize(context_, is_using_bind_uniform_);
   2823   }
   2824   return program.get();
   2825 }
   2826 
   2827 const GLRenderer::TileProgramSwizzleOpaque*
   2828 GLRenderer::GetTileProgramSwizzleOpaque(TexCoordPrecision precision) {
   2829   scoped_ptr<TileProgramSwizzleOpaque>& program =
   2830       (precision == TexCoordPrecisionHigh) ? tile_program_swizzle_opaque_highp_
   2831                                            : tile_program_swizzle_opaque_;
   2832   if (!program)
   2833     program = make_scoped_ptr(
   2834         new TileProgramSwizzleOpaque(context_, precision));
   2835   if (!program->initialized()) {
   2836     TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleOpaque::initialize");
   2837     program->Initialize(context_, is_using_bind_uniform_);
   2838   }
   2839   return program.get();
   2840 }
   2841 
   2842 const GLRenderer::TileProgramSwizzleAA* GLRenderer::GetTileProgramSwizzleAA(
   2843     TexCoordPrecision precision) {
   2844   scoped_ptr<TileProgramSwizzleAA>& program =
   2845       (precision == TexCoordPrecisionHigh) ? tile_program_swizzle_aa_highp_
   2846                                            : tile_program_swizzle_aa_;
   2847   if (!program)
   2848     program = make_scoped_ptr(new TileProgramSwizzleAA(context_, precision));
   2849   if (!program->initialized()) {
   2850     TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleAA::initialize");
   2851     program->Initialize(context_, is_using_bind_uniform_);
   2852   }
   2853   return program.get();
   2854 }
   2855 
   2856 const GLRenderer::TextureProgram* GLRenderer::GetTextureProgram(
   2857     TexCoordPrecision precision) {
   2858   scoped_ptr<TextureProgram>& program =
   2859       (precision == TexCoordPrecisionHigh) ? texture_program_highp_
   2860                                            : texture_program_;
   2861   if (!program)
   2862     program = make_scoped_ptr(new TextureProgram(context_, precision));
   2863   if (!program->initialized()) {
   2864     TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize");
   2865     program->Initialize(context_, is_using_bind_uniform_);
   2866   }
   2867   return program.get();
   2868 }
   2869 
   2870 const GLRenderer::NonPremultipliedTextureProgram*
   2871     GLRenderer::GetNonPremultipliedTextureProgram(TexCoordPrecision precision) {
   2872   scoped_ptr<NonPremultipliedTextureProgram>& program =
   2873       (precision == TexCoordPrecisionHigh) ?
   2874          nonpremultiplied_texture_program_highp_ :
   2875          nonpremultiplied_texture_program_;
   2876   if (!program) {
   2877     program = make_scoped_ptr(
   2878         new NonPremultipliedTextureProgram(context_, precision));
   2879   }
   2880   if (!program->initialized()) {
   2881     TRACE_EVENT0("cc",
   2882                  "GLRenderer::NonPremultipliedTextureProgram::Initialize");
   2883     program->Initialize(context_, is_using_bind_uniform_);
   2884   }
   2885   return program.get();
   2886 }
   2887 
   2888 const GLRenderer::TextureBackgroundProgram*
   2889 GLRenderer::GetTextureBackgroundProgram(TexCoordPrecision precision) {
   2890   scoped_ptr<TextureBackgroundProgram>& program =
   2891       (precision == TexCoordPrecisionHigh) ? texture_background_program_highp_
   2892                                            : texture_background_program_;
   2893   if (!program) {
   2894     program = make_scoped_ptr(
   2895         new TextureBackgroundProgram(context_, precision));
   2896   }
   2897   if (!program->initialized()) {
   2898     TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize");
   2899     program->Initialize(context_, is_using_bind_uniform_);
   2900   }
   2901   return program.get();
   2902 }
   2903 
   2904 const GLRenderer::NonPremultipliedTextureBackgroundProgram*
   2905 GLRenderer::GetNonPremultipliedTextureBackgroundProgram(
   2906     TexCoordPrecision precision) {
   2907   scoped_ptr<NonPremultipliedTextureBackgroundProgram>& program =
   2908       (precision == TexCoordPrecisionHigh) ?
   2909          nonpremultiplied_texture_background_program_highp_ :
   2910          nonpremultiplied_texture_background_program_;
   2911   if (!program) {
   2912     program = make_scoped_ptr(
   2913         new NonPremultipliedTextureBackgroundProgram(context_, precision));
   2914   }
   2915   if (!program->initialized()) {
   2916     TRACE_EVENT0("cc",
   2917                  "GLRenderer::NonPremultipliedTextureProgram::Initialize");
   2918     program->Initialize(context_, is_using_bind_uniform_);
   2919   }
   2920   return program.get();
   2921 }
   2922 
   2923 const GLRenderer::TextureIOSurfaceProgram*
   2924 GLRenderer::GetTextureIOSurfaceProgram(TexCoordPrecision precision) {
   2925   scoped_ptr<TextureIOSurfaceProgram>& program =
   2926       (precision == TexCoordPrecisionHigh) ? texture_io_surface_program_highp_
   2927                                            : texture_io_surface_program_;
   2928   if (!program)
   2929     program =
   2930         make_scoped_ptr(new TextureIOSurfaceProgram(context_, precision));
   2931   if (!program->initialized()) {
   2932     TRACE_EVENT0("cc", "GLRenderer::textureIOSurfaceProgram::initialize");
   2933     program->Initialize(context_, is_using_bind_uniform_);
   2934   }
   2935   return program.get();
   2936 }
   2937 
   2938 const GLRenderer::VideoYUVProgram* GLRenderer::GetVideoYUVProgram(
   2939     TexCoordPrecision precision) {
   2940   scoped_ptr<VideoYUVProgram>& program =
   2941       (precision == TexCoordPrecisionHigh) ? video_yuv_program_highp_
   2942                                            : video_yuv_program_;
   2943   if (!program)
   2944     program = make_scoped_ptr(new VideoYUVProgram(context_, precision));
   2945   if (!program->initialized()) {
   2946     TRACE_EVENT0("cc", "GLRenderer::videoYUVProgram::initialize");
   2947     program->Initialize(context_, is_using_bind_uniform_);
   2948   }
   2949   return program.get();
   2950 }
   2951 
   2952 const GLRenderer::VideoYUVAProgram* GLRenderer::GetVideoYUVAProgram(
   2953     TexCoordPrecision precision) {
   2954   scoped_ptr<VideoYUVAProgram>& program =
   2955       (precision == TexCoordPrecisionHigh) ? video_yuva_program_highp_
   2956                                            : video_yuva_program_;
   2957   if (!program)
   2958     program = make_scoped_ptr(new VideoYUVAProgram(context_, precision));
   2959   if (!program->initialized()) {
   2960     TRACE_EVENT0("cc", "GLRenderer::videoYUVAProgram::initialize");
   2961     program->Initialize(context_, is_using_bind_uniform_);
   2962   }
   2963   return program.get();
   2964 }
   2965 
   2966 const GLRenderer::VideoStreamTextureProgram*
   2967 GLRenderer::GetVideoStreamTextureProgram(TexCoordPrecision precision) {
   2968   if (!Capabilities().using_egl_image)
   2969     return NULL;
   2970   scoped_ptr<VideoStreamTextureProgram>& program =
   2971       (precision == TexCoordPrecisionHigh) ? video_stream_texture_program_highp_
   2972                                            : video_stream_texture_program_;
   2973   if (!program)
   2974     program =
   2975         make_scoped_ptr(new VideoStreamTextureProgram(context_, precision));
   2976   if (!program->initialized()) {
   2977     TRACE_EVENT0("cc", "GLRenderer::streamTextureProgram::initialize");
   2978     program->Initialize(context_, is_using_bind_uniform_);
   2979   }
   2980   return program.get();
   2981 }
   2982 
   2983 void GLRenderer::CleanupSharedObjects() {
   2984   MakeContextCurrent();
   2985 
   2986   shared_geometry_.reset();
   2987 
   2988   if (tile_program_)
   2989     tile_program_->Cleanup(context_);
   2990   if (tile_program_opaque_)
   2991     tile_program_opaque_->Cleanup(context_);
   2992   if (tile_program_swizzle_)
   2993     tile_program_swizzle_->Cleanup(context_);
   2994   if (tile_program_swizzle_opaque_)
   2995     tile_program_swizzle_opaque_->Cleanup(context_);
   2996   if (tile_program_aa_)
   2997     tile_program_aa_->Cleanup(context_);
   2998   if (tile_program_swizzle_aa_)
   2999     tile_program_swizzle_aa_->Cleanup(context_);
   3000   if (tile_checkerboard_program_)
   3001     tile_checkerboard_program_->Cleanup(context_);
   3002 
   3003   if (tile_program_highp_)
   3004     tile_program_highp_->Cleanup(context_);
   3005   if (tile_program_opaque_highp_)
   3006     tile_program_opaque_highp_->Cleanup(context_);
   3007   if (tile_program_swizzle_highp_)
   3008     tile_program_swizzle_highp_->Cleanup(context_);
   3009   if (tile_program_swizzle_opaque_highp_)
   3010     tile_program_swizzle_opaque_highp_->Cleanup(context_);
   3011   if (tile_program_aa_highp_)
   3012     tile_program_aa_highp_->Cleanup(context_);
   3013   if (tile_program_swizzle_aa_highp_)
   3014     tile_program_swizzle_aa_highp_->Cleanup(context_);
   3015 
   3016   if (render_pass_mask_program_)
   3017     render_pass_mask_program_->Cleanup(context_);
   3018   if (render_pass_program_)
   3019     render_pass_program_->Cleanup(context_);
   3020   if (render_pass_mask_program_aa_)
   3021     render_pass_mask_program_aa_->Cleanup(context_);
   3022   if (render_pass_program_aa_)
   3023     render_pass_program_aa_->Cleanup(context_);
   3024   if (render_pass_color_matrix_program_)
   3025     render_pass_color_matrix_program_->Cleanup(context_);
   3026   if (render_pass_mask_color_matrix_program_aa_)
   3027     render_pass_mask_color_matrix_program_aa_->Cleanup(context_);
   3028   if (render_pass_color_matrix_program_aa_)
   3029     render_pass_color_matrix_program_aa_->Cleanup(context_);
   3030   if (render_pass_mask_color_matrix_program_)
   3031     render_pass_mask_color_matrix_program_->Cleanup(context_);
   3032 
   3033   if (render_pass_mask_program_highp_)
   3034     render_pass_mask_program_highp_->Cleanup(context_);
   3035   if (render_pass_program_highp_)
   3036     render_pass_program_highp_->Cleanup(context_);
   3037   if (render_pass_mask_program_aa_highp_)
   3038     render_pass_mask_program_aa_highp_->Cleanup(context_);
   3039   if (render_pass_program_aa_highp_)
   3040     render_pass_program_aa_highp_->Cleanup(context_);
   3041   if (render_pass_color_matrix_program_highp_)
   3042     render_pass_color_matrix_program_highp_->Cleanup(context_);
   3043   if (render_pass_mask_color_matrix_program_aa_highp_)
   3044     render_pass_mask_color_matrix_program_aa_highp_->Cleanup(context_);
   3045   if (render_pass_color_matrix_program_aa_highp_)
   3046     render_pass_color_matrix_program_aa_highp_->Cleanup(context_);
   3047   if (render_pass_mask_color_matrix_program_highp_)
   3048     render_pass_mask_color_matrix_program_highp_->Cleanup(context_);
   3049 
   3050   if (texture_program_)
   3051     texture_program_->Cleanup(context_);
   3052   if (nonpremultiplied_texture_program_)
   3053     nonpremultiplied_texture_program_->Cleanup(context_);
   3054   if (texture_background_program_)
   3055     texture_background_program_->Cleanup(context_);
   3056   if (nonpremultiplied_texture_background_program_)
   3057     nonpremultiplied_texture_background_program_->Cleanup(context_);
   3058   if (texture_io_surface_program_)
   3059     texture_io_surface_program_->Cleanup(context_);
   3060 
   3061   if (texture_program_highp_)
   3062     texture_program_highp_->Cleanup(context_);
   3063   if (nonpremultiplied_texture_program_highp_)
   3064     nonpremultiplied_texture_program_highp_->Cleanup(context_);
   3065   if (texture_background_program_highp_)
   3066     texture_background_program_highp_->Cleanup(context_);
   3067   if (nonpremultiplied_texture_background_program_highp_)
   3068     nonpremultiplied_texture_background_program_highp_->Cleanup(context_);
   3069   if (texture_io_surface_program_highp_)
   3070     texture_io_surface_program_highp_->Cleanup(context_);
   3071 
   3072   if (video_yuv_program_)
   3073     video_yuv_program_->Cleanup(context_);
   3074   if (video_yuva_program_)
   3075     video_yuva_program_->Cleanup(context_);
   3076   if (video_stream_texture_program_)
   3077     video_stream_texture_program_->Cleanup(context_);
   3078 
   3079   if (video_yuv_program_highp_)
   3080     video_yuv_program_highp_->Cleanup(context_);
   3081   if (video_yuva_program_highp_)
   3082     video_yuva_program_highp_->Cleanup(context_);
   3083   if (video_stream_texture_program_highp_)
   3084     video_stream_texture_program_highp_->Cleanup(context_);
   3085 
   3086   if (debug_border_program_)
   3087     debug_border_program_->Cleanup(context_);
   3088   if (solid_color_program_)
   3089     solid_color_program_->Cleanup(context_);
   3090   if (solid_color_program_aa_)
   3091     solid_color_program_aa_->Cleanup(context_);
   3092 
   3093   if (offscreen_framebuffer_id_)
   3094     GLC(context_, context_->deleteFramebuffer(offscreen_framebuffer_id_));
   3095 
   3096   if (on_demand_tile_raster_resource_id_)
   3097     resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_);
   3098 
   3099   ReleaseRenderPassTextures();
   3100 }
   3101 
   3102 void GLRenderer::ReinitializeGrCanvas() {
   3103   if (!CanUseSkiaGPUBackend())
   3104     return;
   3105 
   3106   GrBackendRenderTargetDesc desc;
   3107   desc.fWidth = client_->DeviceViewport().width();
   3108   desc.fHeight = client_->DeviceViewport().height();
   3109   desc.fConfig = kRGBA_8888_GrPixelConfig;
   3110   desc.fOrigin = kTopLeft_GrSurfaceOrigin;
   3111   desc.fSampleCnt = 1;
   3112   desc.fStencilBits = 8;
   3113   desc.fRenderTargetHandle = 0;
   3114 
   3115   skia::RefPtr<GrSurface> surface(
   3116       skia::AdoptRef(gr_context_->wrapBackendRenderTarget(desc)));
   3117   skia::RefPtr<SkDevice> device(
   3118       skia::AdoptRef(SkGpuDevice::Create(surface.get())));
   3119   sk_canvas_ = skia::AdoptRef(new SkCanvas(device.get()));
   3120 }
   3121 
   3122 void GLRenderer::ReinitializeGLState() {
   3123   // Bind the common vertex attributes used for drawing all the layers.
   3124   shared_geometry_->PrepareForDraw();
   3125 
   3126   GLC(context_, context_->disable(GL_DEPTH_TEST));
   3127   GLC(context_, context_->disable(GL_CULL_FACE));
   3128   GLC(context_, context_->colorMask(true, true, true, true));
   3129   GLC(context_, context_->disable(GL_STENCIL_TEST));
   3130   stencil_shadow_ = false;
   3131   GLC(context_, context_->enable(GL_BLEND));
   3132   blend_shadow_ = true;
   3133   GLC(context_, context_->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
   3134   GLC(context_, context_->activeTexture(GL_TEXTURE0));
   3135   program_shadow_ = 0;
   3136 
   3137   // Make sure scissoring starts as disabled.
   3138   is_scissor_enabled_ = false;
   3139   GLC(context_, context_->disable(GL_SCISSOR_TEST));
   3140 }
   3141 
   3142 bool GLRenderer::CanUseSkiaGPUBackend() const {
   3143   // The Skia GPU backend requires a stencil buffer.  See ReinitializeGrCanvas
   3144   // implementation.
   3145   return gr_context_ && context_->getContextAttributes().stencil;
   3146 }
   3147 
   3148 bool GLRenderer::IsContextLost() {
   3149   return (context_->getGraphicsResetStatusARB() != GL_NO_ERROR);
   3150 }
   3151 
   3152 void GLRenderer::LazyLabelOffscreenContext() {
   3153   if (offscreen_context_labelled_)
   3154     return;
   3155   offscreen_context_labelled_ = true;
   3156   std::string unique_context_name = base::StringPrintf(
   3157       "%s-Offscreen-%p",
   3158       Settings().compositor_name.c_str(),
   3159       context_);
   3160   resource_provider()->offscreen_context_provider()->Context3d()->
   3161     pushGroupMarkerEXT(unique_context_name.c_str());
   3162 }
   3163 
   3164 
   3165 }  // namespace cc
   3166