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