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