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