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