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