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.
5 #include "cc/output/gl_renderer.h"
12 #include "base/debug/trace_event.h"
13 #include "base/logging.h"
14 #include "base/string_util.h"
15 #include "base/strings/string_split.h"
16 #include "build/build_config.h"
17 #include "cc/base/math_util.h"
18 #include "cc/layers/video_layer_impl.h"
19 #include "cc/output/compositor_frame.h"
20 #include "cc/output/compositor_frame_metadata.h"
21 #include "cc/output/context_provider.h"
22 #include "cc/output/geometry_binding.h"
23 #include "cc/output/gl_frame_data.h"
24 #include "cc/output/output_surface.h"
25 #include "cc/output/render_surface_filters.h"
26 #include "cc/quads/picture_draw_quad.h"
27 #include "cc/quads/render_pass.h"
28 #include "cc/quads/stream_video_draw_quad.h"
29 #include "cc/quads/texture_draw_quad.h"
30 #include "cc/resources/layer_quad.h"
31 #include "cc/resources/priority_calculator.h"
32 #include "cc/resources/scoped_resource.h"
33 #include "cc/trees/damage_tracker.h"
34 #include "cc/trees/proxy.h"
35 #include "cc/trees/single_thread_proxy.h"
36 #include "gpu/GLES2/gl2extchromium.h"
37 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
38 #include "third_party/khronos/GLES2/gl2.h"
39 #include "third_party/khronos/GLES2/gl2ext.h"
40 #include "third_party/skia/include/core/SkBitmap.h"
41 #include "third_party/skia/include/core/SkColor.h"
42 #include "third_party/skia/include/core/SkColorFilter.h"
43 #include "third_party/skia/include/gpu/GrContext.h"
44 #include "third_party/skia/include/gpu/GrTexture.h"
45 #include "third_party/skia/include/gpu/SkGpuDevice.h"
46 #include "third_party/skia/include/gpu/SkGrTexturePixelRef.h"
47 #include "ui/gfx/quad_f.h"
48 #include "ui/gfx/rect_conversions.h"
50 using WebKit::WebGraphicsContext3D
;
51 using WebKit::WebGraphicsMemoryAllocation
;
57 // TODO(epenner): This should probably be moved to output surface.
59 // This implements a simple fence based on client side swaps.
60 // This is to isolate the ResourceProvider from 'frames' which
61 // it shouldn't need to care about, while still allowing us to
62 // enforce good texture recycling behavior strictly throughout
63 // the compositor (don't recycle a texture while it's in use).
64 class SimpleSwapFence
: public ResourceProvider::Fence
{
66 SimpleSwapFence() : has_passed_(false) {}
67 virtual bool HasPassed() OVERRIDE
{ return has_passed_
; }
68 void SetHasPassed() { has_passed_
= true; }
70 virtual ~SimpleSwapFence() {}
74 bool NeedsIOSurfaceReadbackWorkaround() {
75 #if defined(OS_MACOSX)
76 // This isn't strictly required in DumpRenderTree-mode when Mesa is used,
77 // but it doesn't seem to hurt.
84 } // anonymous namespace
86 scoped_ptr
<GLRenderer
> GLRenderer::Create(RendererClient
* client
,
87 OutputSurface
* output_surface
,
88 ResourceProvider
* resource_provider
,
89 int highp_threshold_min
) {
90 scoped_ptr
<GLRenderer
> renderer(new GLRenderer(
91 client
, output_surface
, resource_provider
, highp_threshold_min
));
92 if (!renderer
->Initialize())
93 return scoped_ptr
<GLRenderer
>();
95 return renderer
.Pass();
98 GLRenderer::GLRenderer(RendererClient
* client
,
99 OutputSurface
* output_surface
,
100 ResourceProvider
* resource_provider
,
101 int highp_threshold_min
)
102 : DirectRenderer(client
, resource_provider
),
103 offscreen_framebuffer_id_(0),
104 shared_geometry_quad_(gfx::RectF(-0.5f
, -0.5f
, 1.0f
, 1.0f
)),
105 output_surface_(output_surface
),
106 context_(output_surface
->context3d()),
107 is_viewport_changed_(false),
108 is_backbuffer_discarded_(false),
109 discard_backbuffer_when_not_visible_(false),
110 is_using_bind_uniform_(false),
112 is_scissor_enabled_(false),
113 highp_threshold_min_(highp_threshold_min
),
114 on_demand_tile_raster_resource_id_(0) {
118 bool GLRenderer::Initialize() {
119 if (!context_
->makeContextCurrent())
122 context_
->setContextLostCallback(this);
123 context_
->pushGroupMarkerEXT("CompositorContext");
125 std::string extensions_string
=
126 UTF16ToASCII(context_
->getString(GL_EXTENSIONS
));
127 std::vector
<std::string
> extensions_list
;
128 base::SplitString(extensions_string
, ' ', &extensions_list
);
129 std::set
<std::string
> extensions(extensions_list
.begin(),
130 extensions_list
.end());
132 if (Settings().accelerate_painting
&&
133 extensions
.count("GL_EXT_texture_format_BGRA8888") &&
134 extensions
.count("GL_EXT_read_format_bgra"))
135 capabilities_
.using_accelerated_painting
= true;
137 capabilities_
.using_accelerated_painting
= false;
139 capabilities_
.using_partial_swap
=
140 Settings().partial_swap_enabled
&&
141 extensions
.count("GL_CHROMIUM_post_sub_buffer");
143 // Use the SwapBuffers callback only with the threaded proxy.
144 if (client_
->HasImplThread())
145 capabilities_
.using_swap_complete_callback
=
146 extensions
.count("GL_CHROMIUM_swapbuffers_complete_callback") > 0;
147 if (capabilities_
.using_swap_complete_callback
)
148 context_
->setSwapBuffersCompleteCallbackCHROMIUM(this);
150 capabilities_
.using_set_visibility
=
151 extensions
.count("GL_CHROMIUM_set_visibility") > 0;
153 if (extensions
.count("GL_CHROMIUM_iosurface") > 0)
154 DCHECK(extensions
.count("GL_ARB_texture_rectangle") > 0);
156 capabilities_
.using_gpu_memory_manager
=
157 extensions
.count("GL_CHROMIUM_gpu_memory_manager") > 0 &&
158 Settings().use_memory_management
;
159 if (capabilities_
.using_gpu_memory_manager
)
160 context_
->setMemoryAllocationChangedCallbackCHROMIUM(this);
162 capabilities_
.using_egl_image
=
163 extensions
.count("GL_OES_EGL_image_external") > 0;
165 capabilities_
.max_texture_size
= resource_provider_
->max_texture_size();
166 capabilities_
.best_texture_format
= resource_provider_
->best_texture_format();
168 // The updater can access textures while the GLRenderer is using them.
169 capabilities_
.allow_partial_texture_updates
= true;
171 // Check for texture fast paths. Currently we always use MO8 textures,
172 // so we only need to avoid POT textures if we have an NPOT fast-path.
173 capabilities_
.avoid_pow2_textures
=
174 extensions
.count("GL_CHROMIUM_fast_NPOT_MO8_textures") > 0;
176 capabilities_
.using_offscreen_context3d
= true;
178 is_using_bind_uniform_
=
179 extensions
.count("GL_CHROMIUM_bind_uniform_location") > 0;
181 // Make sure scissoring starts as disabled.
182 GLC(context_
, context_
->disable(GL_SCISSOR_TEST
));
183 DCHECK(!is_scissor_enabled_
);
185 if (!InitializeSharedObjects())
188 // Make sure the viewport and context gets initialized, even if it is to zero.
193 GLRenderer::~GLRenderer() {
194 context_
->setSwapBuffersCompleteCallbackCHROMIUM(NULL
);
195 context_
->setMemoryAllocationChangedCallbackCHROMIUM(NULL
);
196 context_
->setContextLostCallback(NULL
);
197 CleanupSharedObjects();
200 const RendererCapabilities
& GLRenderer::Capabilities() const {
201 return capabilities_
;
204 WebGraphicsContext3D
* GLRenderer::Context() { return context_
; }
206 void GLRenderer::DebugGLCall(WebGraphicsContext3D
* context
,
210 unsigned error
= context
->getError();
211 if (error
!= GL_NO_ERROR
)
212 LOG(ERROR
) << "GL command failed: File: " << file
<< "\n\tLine " << line
213 << "\n\tcommand: " << command
<< ", error "
214 << static_cast<int>(error
) << "\n";
217 void GLRenderer::SetVisible(bool visible
) {
218 if (visible_
== visible
)
222 EnforceMemoryPolicy();
224 // TODO(jamesr): Replace setVisibilityCHROMIUM() with an extension to
225 // explicitly manage front/backbuffers
227 if (capabilities_
.using_set_visibility
)
228 context_
->setVisibilityCHROMIUM(visible
);
231 void GLRenderer::SendManagedMemoryStats(size_t bytes_visible
,
232 size_t bytes_visible_and_nearby
,
233 size_t bytes_allocated
) {
234 WebKit::WebGraphicsManagedMemoryStats stats
;
235 stats
.bytesVisible
= bytes_visible
;
236 stats
.bytesVisibleAndNearby
= bytes_visible_and_nearby
;
237 stats
.bytesAllocated
= bytes_allocated
;
238 stats
.backbufferRequested
= !is_backbuffer_discarded_
;
239 context_
->sendManagedMemoryStatsCHROMIUM(&stats
);
242 void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_
.clear(); }
244 void GLRenderer::ViewportChanged() { is_viewport_changed_
= true; }
246 void GLRenderer::ClearFramebuffer(DrawingFrame
* frame
) {
247 // On DEBUG builds, opaque render passes are cleared to blue to easily see
248 // regions that were not drawn on the screen.
249 if (frame
->current_render_pass
->has_transparent_background
)
250 GLC(context_
, context_
->clearColor(0, 0, 0, 0));
252 GLC(context_
, context_
->clearColor(0, 0, 1, 1));
255 if (frame
->current_render_pass
->has_transparent_background
)
257 context_
->clear(GL_COLOR_BUFFER_BIT
);
260 void GLRenderer::BeginDrawingFrame(DrawingFrame
* frame
) {
261 // FIXME: Remove this once backbuffer is automatically recreated on first use
264 if (ViewportSize().IsEmpty())
267 TRACE_EVENT0("cc", "GLRenderer::DrawLayers");
268 if (is_viewport_changed_
) {
269 // Only reshape when we know we are going to draw. Otherwise, the reshape
270 // can leave the window at the wrong size if we never draw and the proper
271 // viewport size is never set.
272 is_viewport_changed_
= false;
273 output_surface_
->Reshape(gfx::Size(ViewportWidth(), ViewportHeight()));
276 MakeContextCurrent();
277 // Bind the common vertex attributes used for drawing all the layers.
278 shared_geometry_
->PrepareForDraw();
280 GLC(context_
, context_
->disable(GL_DEPTH_TEST
));
281 GLC(context_
, context_
->disable(GL_CULL_FACE
));
282 GLC(context_
, context_
->colorMask(true, true, true, true));
283 GLC(context_
, context_
->enable(GL_BLEND
));
284 blend_shadow_
= true;
285 GLC(context_
, context_
->blendFunc(GL_ONE
, GL_ONE_MINUS_SRC_ALPHA
));
286 GLC(Context(), Context()->activeTexture(GL_TEXTURE0
));
290 void GLRenderer::DoNoOp() {
291 GLC(context_
, context_
->bindFramebuffer(GL_FRAMEBUFFER
, 0));
292 GLC(context_
, context_
->flush());
295 void GLRenderer::DoDrawQuad(DrawingFrame
* frame
, const DrawQuad
* quad
) {
296 DCHECK(quad
->rect
.Contains(quad
->visible_rect
));
297 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
) {
298 FlushTextureQuadCache();
301 switch (quad
->material
) {
302 case DrawQuad::INVALID
:
305 case DrawQuad::CHECKERBOARD
:
306 DrawCheckerboardQuad(frame
, CheckerboardDrawQuad::MaterialCast(quad
));
308 case DrawQuad::DEBUG_BORDER
:
309 DrawDebugBorderQuad(frame
, DebugBorderDrawQuad::MaterialCast(quad
));
311 case DrawQuad::IO_SURFACE_CONTENT
:
312 DrawIOSurfaceQuad(frame
, IOSurfaceDrawQuad::MaterialCast(quad
));
314 case DrawQuad::PICTURE_CONTENT
:
315 DrawPictureQuad(frame
, PictureDrawQuad::MaterialCast(quad
));
317 case DrawQuad::RENDER_PASS
:
318 DrawRenderPassQuad(frame
, RenderPassDrawQuad::MaterialCast(quad
));
320 case DrawQuad::SOLID_COLOR
:
321 DrawSolidColorQuad(frame
, SolidColorDrawQuad::MaterialCast(quad
));
323 case DrawQuad::STREAM_VIDEO_CONTENT
:
324 DrawStreamVideoQuad(frame
, StreamVideoDrawQuad::MaterialCast(quad
));
326 case DrawQuad::TEXTURE_CONTENT
:
327 EnqueueTextureQuad(frame
, TextureDrawQuad::MaterialCast(quad
));
329 case DrawQuad::TILED_CONTENT
:
330 DrawTileQuad(frame
, TileDrawQuad::MaterialCast(quad
));
332 case DrawQuad::YUV_VIDEO_CONTENT
:
333 DrawYUVVideoQuad(frame
, YUVVideoDrawQuad::MaterialCast(quad
));
338 void GLRenderer::DrawCheckerboardQuad(const DrawingFrame
* frame
,
339 const CheckerboardDrawQuad
* quad
) {
340 SetBlendEnabled(quad
->ShouldDrawWithBlending());
342 const TileCheckerboardProgram
* program
= GetTileCheckerboardProgram();
343 DCHECK(program
&& (program
->initialized() || IsContextLost()));
344 SetUseProgram(program
->program());
346 SkColor color
= quad
->color
;
348 Context()->uniform4f(program
->fragment_shader().color_location(),
349 SkColorGetR(color
) * (1.0f
/ 255.0f
),
350 SkColorGetG(color
) * (1.0f
/ 255.0f
),
351 SkColorGetB(color
) * (1.0f
/ 255.0f
),
354 const int checkerboard_width
= 16;
355 float frequency
= 1.0f
/ checkerboard_width
;
357 gfx::Rect tile_rect
= quad
->rect
;
358 float tex_offset_x
= tile_rect
.x() % checkerboard_width
;
359 float tex_offset_y
= tile_rect
.y() % checkerboard_width
;
360 float tex_scale_x
= tile_rect
.width();
361 float tex_scale_y
= tile_rect
.height();
363 Context()->uniform4f(program
->fragment_shader().tex_transform_location(),
370 Context()->uniform1f(program
->fragment_shader().frequency_location(),
373 SetShaderOpacity(quad
->opacity(),
374 program
->fragment_shader().alpha_location());
375 DrawQuadGeometry(frame
,
376 quad
->quadTransform(),
378 program
->vertex_shader().matrix_location());
381 void GLRenderer::DrawDebugBorderQuad(const DrawingFrame
* frame
,
382 const DebugBorderDrawQuad
* quad
) {
383 SetBlendEnabled(quad
->ShouldDrawWithBlending());
385 static float gl_matrix
[16];
386 const DebugBorderProgram
* program
= GetDebugBorderProgram();
387 DCHECK(program
&& (program
->initialized() || IsContextLost()));
388 SetUseProgram(program
->program());
390 // Use the full quad_rect for debug quads to not move the edges based on
392 gfx::Rect layer_rect
= quad
->rect
;
393 gfx::Transform render_matrix
= quad
->quadTransform();
394 render_matrix
.Translate(0.5f
* layer_rect
.width() + layer_rect
.x(),
395 0.5f
* layer_rect
.height() + layer_rect
.y());
396 render_matrix
.Scale(layer_rect
.width(), layer_rect
.height());
397 GLRenderer::ToGLMatrix(&gl_matrix
[0],
398 frame
->projection_matrix
* render_matrix
);
400 Context()->uniformMatrix4fv(
401 program
->vertex_shader().matrix_location(), 1, false, &gl_matrix
[0]));
403 SkColor color
= quad
->color
;
404 float alpha
= SkColorGetA(color
) * (1.0f
/ 255.0f
);
407 Context()->uniform4f(program
->fragment_shader().color_location(),
408 (SkColorGetR(color
) * (1.0f
/ 255.0f
)) * alpha
,
409 (SkColorGetG(color
) * (1.0f
/ 255.0f
)) * alpha
,
410 (SkColorGetB(color
) * (1.0f
/ 255.0f
)) * alpha
,
413 GLC(Context(), Context()->lineWidth(quad
->width
));
415 // The indices for the line are stored in the same array as the triangle
418 Context()->drawElements(GL_LINE_LOOP
, 4, GL_UNSIGNED_SHORT
, 0));
421 static inline SkBitmap
ApplyFilters(GLRenderer
* renderer
,
422 const WebKit::WebFilterOperations
& filters
,
423 ScopedResource
* source_texture_resource
) {
424 if (filters
.isEmpty())
427 ContextProvider
* offscreen_contexts
=
428 renderer
->resource_provider()->offscreen_context_provider();
429 if (!offscreen_contexts
|| !offscreen_contexts
->GrContext())
432 ResourceProvider::ScopedWriteLockGL
lock(renderer
->resource_provider(),
433 source_texture_resource
->id());
435 // Flush the compositor context to ensure that textures there are available
436 // in the shared context. Do this after locking/creating the compositor
438 renderer
->resource_provider()->Flush();
440 // Make sure skia uses the correct GL context.
441 offscreen_contexts
->Context3d()->makeContextCurrent();
444 RenderSurfaceFilters::Apply(filters
,
446 source_texture_resource
->size(),
447 offscreen_contexts
->GrContext());
449 // Flush skia context so that all the rendered stuff appears on the
451 offscreen_contexts
->GrContext()->flush();
453 // Flush the GL context so rendering results from this context are
454 // visible in the compositor's context.
455 offscreen_contexts
->Context3d()->flush();
457 // Use the compositor's GL context again.
458 renderer
->resource_provider()->GraphicsContext3D()->makeContextCurrent();
462 static SkBitmap
ApplyImageFilter(GLRenderer
* renderer
,
463 SkImageFilter
* filter
,
464 ScopedResource
* source_texture_resource
) {
468 ContextProvider
* offscreen_contexts
=
469 renderer
->resource_provider()->offscreen_context_provider();
470 if (!offscreen_contexts
|| !offscreen_contexts
->GrContext())
473 ResourceProvider::ScopedWriteLockGL
lock(renderer
->resource_provider(),
474 source_texture_resource
->id());
476 // Flush the compositor context to ensure that textures there are available
477 // in the shared context. Do this after locking/creating the compositor
479 renderer
->resource_provider()->Flush();
481 // Make sure skia uses the correct GL context.
482 offscreen_contexts
->Context3d()->makeContextCurrent();
484 // Wrap the source texture in a Ganesh platform texture.
485 GrBackendTextureDesc backend_texture_description
;
486 backend_texture_description
.fWidth
= source_texture_resource
->size().width();
487 backend_texture_description
.fHeight
=
488 source_texture_resource
->size().height();
489 backend_texture_description
.fConfig
= kSkia8888_GrPixelConfig
;
490 backend_texture_description
.fTextureHandle
= lock
.texture_id();
491 backend_texture_description
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
492 skia::RefPtr
<GrTexture
> texture
=
493 skia::AdoptRef(offscreen_contexts
->GrContext()->wrapBackendTexture(
494 backend_texture_description
));
496 // Place the platform texture inside an SkBitmap.
498 source
.setConfig(SkBitmap::kARGB_8888_Config
,
499 source_texture_resource
->size().width(),
500 source_texture_resource
->size().height());
501 skia::RefPtr
<SkGrPixelRef
> pixel_ref
=
502 skia::AdoptRef(new SkGrPixelRef(texture
.get()));
503 source
.setPixelRef(pixel_ref
.get());
505 // Create a scratch texture for backing store.
507 desc
.fFlags
= kRenderTarget_GrTextureFlagBit
| kNoStencil_GrTextureFlagBit
;
509 desc
.fWidth
= source
.width();
510 desc
.fHeight
= source
.height();
511 desc
.fConfig
= kSkia8888_GrPixelConfig
;
512 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
513 GrAutoScratchTexture
scratch_texture(
514 offscreen_contexts
->GrContext(), desc
, GrContext::kExact_ScratchTexMatch
);
515 skia::RefPtr
<GrTexture
> backing_store
=
516 skia::AdoptRef(scratch_texture
.detach());
518 // Create a device and canvas using that backing store.
519 SkGpuDevice
device(offscreen_contexts
->GrContext(), backing_store
.get());
520 SkCanvas
canvas(&device
);
522 // Draw the source bitmap through the filter to the canvas.
524 paint
.setImageFilter(filter
);
525 canvas
.clear(SK_ColorTRANSPARENT
);
526 canvas
.drawSprite(source
, 0, 0, &paint
);
528 // Flush skia context so that all the rendered stuff appears on the
530 offscreen_contexts
->GrContext()->flush();
532 // Flush the GL context so rendering results from this context are
533 // visible in the compositor's context.
534 offscreen_contexts
->Context3d()->flush();
536 // Use the compositor's GL context again.
537 renderer
->resource_provider()->GraphicsContext3D()->makeContextCurrent();
539 return device
.accessBitmap(false);
542 scoped_ptr
<ScopedResource
> GLRenderer::DrawBackgroundFilters(
544 const RenderPassDrawQuad
* quad
,
545 const gfx::Transform
& contents_device_transform
,
546 const gfx::Transform
& contents_device_transform_inverse
) {
547 // This method draws a background filter, which applies a filter to any pixels
548 // behind the quad and seen through its background. The algorithm works as
550 // 1. Compute a bounding box around the pixels that will be visible through
552 // 2. Read the pixels in the bounding box into a buffer R.
553 // 3. Apply the background filter to R, so that it is applied in the pixels'
555 // 4. Apply the quad's inverse transform to map the pixels in R into the
556 // quad's content space. This implicitly clips R by the content bounds of the
557 // quad since the destination texture has bounds matching the quad's content.
558 // 5. Draw the background texture for the contents using the same transform as
559 // used to draw the contents itself. This is done without blending to replace
560 // the current background pixels with the new filtered background.
561 // 6. Draw the contents of the quad over drop of the new background with
562 // blending, as per usual. The filtered background pixels will show through
563 // any non-opaque pixels in this draws.
565 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
567 // FIXME: When this algorithm changes, update
568 // LayerTreeHost::PrioritizeTextures() accordingly.
570 const WebKit::WebFilterOperations
& filters
= quad
->background_filters
;
571 DCHECK(!filters
.isEmpty());
573 // FIXME: We only allow background filters on an opaque render surface because
574 // other surfaces may contain translucent pixels, and the contents behind
575 // those translucent pixels wouldn't have the filter applied.
576 if (frame
->current_render_pass
->has_transparent_background
)
577 return scoped_ptr
<ScopedResource
>();
578 DCHECK(!frame
->current_texture
);
580 // FIXME: Do a single readback for both the surface and replica and cache the
581 // filtered results (once filter textures are not reused).
582 gfx::Rect device_rect
= gfx::ToEnclosingRect(MathUtil::MapClippedRect(
583 contents_device_transform
, SharedGeometryQuad().BoundingBox()));
585 int top
, right
, bottom
, left
;
586 filters
.getOutsets(top
, right
, bottom
, left
);
587 device_rect
.Inset(-left
, -top
, -right
, -bottom
);
589 device_rect
.Intersect(frame
->current_render_pass
->output_rect
);
591 scoped_ptr
<ScopedResource
> device_background_texture
=
592 ScopedResource::create(resource_provider_
);
593 if (!GetFramebufferTexture(device_background_texture
.get(), device_rect
))
594 return scoped_ptr
<ScopedResource
>();
596 SkBitmap filtered_device_background
=
597 ApplyFilters(this, filters
, device_background_texture
.get());
598 if (!filtered_device_background
.getTexture())
599 return scoped_ptr
<ScopedResource
>();
602 reinterpret_cast<GrTexture
*>(filtered_device_background
.getTexture());
603 int filtered_device_background_texture_id
= texture
->getTextureHandle();
605 scoped_ptr
<ScopedResource
> background_texture
=
606 ScopedResource::create(resource_provider_
);
607 if (!background_texture
->Allocate(quad
->rect
.size(),
609 ResourceProvider::TextureUsageFramebuffer
))
610 return scoped_ptr
<ScopedResource
>();
612 const RenderPass
* target_render_pass
= frame
->current_render_pass
;
613 bool using_background_texture
=
614 UseScopedTexture(frame
, background_texture
.get(), quad
->rect
);
616 if (using_background_texture
) {
617 // Copy the readback pixels from device to the background texture for the
619 gfx::Transform device_to_framebuffer_transform
;
620 device_to_framebuffer_transform
.Translate(
621 quad
->rect
.width() * 0.5f
+ quad
->rect
.x(),
622 quad
->rect
.height() * 0.5f
+ quad
->rect
.y());
623 device_to_framebuffer_transform
.Scale(quad
->rect
.width(),
624 quad
->rect
.height());
625 device_to_framebuffer_transform
.PreconcatTransform(
626 contents_device_transform_inverse
);
629 GLC(Context(), Context()->clearColor(0, 0, 1, 1));
630 Context()->clear(GL_COLOR_BUFFER_BIT
);
633 CopyTextureToFramebuffer(frame
,
634 filtered_device_background_texture_id
,
636 device_to_framebuffer_transform
);
639 UseRenderPass(frame
, target_render_pass
);
641 if (!using_background_texture
)
642 return scoped_ptr
<ScopedResource
>();
643 return background_texture
.Pass();
646 void GLRenderer::DrawRenderPassQuad(DrawingFrame
* frame
,
647 const RenderPassDrawQuad
* quad
) {
648 SetBlendEnabled(quad
->ShouldDrawWithBlending());
650 CachedResource
* contents_texture
=
651 render_pass_textures_
.get(quad
->render_pass_id
);
652 if (!contents_texture
|| !contents_texture
->id())
655 gfx::Transform quad_rect_matrix
;
656 QuadRectTransform(&quad_rect_matrix
, quad
->quadTransform(), quad
->rect
);
657 gfx::Transform contents_device_transform
=
658 frame
->window_matrix
* frame
->projection_matrix
* quad_rect_matrix
;
659 contents_device_transform
.FlattenTo2d();
661 // Can only draw surface if device matrix is invertible.
662 gfx::Transform
contents_device_transform_inverse(
663 gfx::Transform::kSkipInitialization
);
664 if (!contents_device_transform
.GetInverse(&contents_device_transform_inverse
))
667 scoped_ptr
<ScopedResource
> background_texture
;
668 if (!quad
->background_filters
.isEmpty()) {
669 // The pixels from the filtered background should completely replace the
670 // current pixel values.
671 bool disable_blending
= blend_enabled();
672 if (disable_blending
)
673 SetBlendEnabled(false);
675 background_texture
= DrawBackgroundFilters(
678 contents_device_transform
,
679 contents_device_transform_inverse
);
681 if (disable_blending
)
682 SetBlendEnabled(true);
685 // FIXME: Cache this value so that we don't have to do it for both the surface
686 // and its replica. Apply filters to the contents texture.
687 SkBitmap filter_bitmap
;
688 SkScalar color_matrix
[20];
689 bool use_color_matrix
= false;
692 if ((quad
->filter
->asColorFilter(&cf
)) && cf
->asColorMatrix(color_matrix
) &&
693 !quad
->filter
->getInput(0)) {
694 // We have a single color matrix as a filter; apply it locally
695 // in the compositor.
696 use_color_matrix
= true;
699 ApplyImageFilter(this, quad
->filter
.get(), contents_texture
);
702 filter_bitmap
= ApplyFilters(this, quad
->filters
, contents_texture
);
705 // Draw the background texture if there is one.
706 if (background_texture
) {
707 DCHECK(background_texture
->size() == quad
->rect
.size());
708 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
,
709 background_texture
->id());
710 CopyTextureToFramebuffer(
711 frame
, lock
.texture_id(), quad
->rect
, quad
->quadTransform());
714 bool clipped
= false;
715 gfx::QuadF device_quad
= MathUtil::MapQuad(
716 contents_device_transform
, SharedGeometryQuad(), &clipped
);
718 LayerQuad
device_layer_bounds(gfx::QuadF(device_quad
.BoundingBox()));
719 LayerQuad
device_layer_edges(device_quad
);
721 // Use anti-aliasing programs only when necessary.
722 bool use_aa
= (!device_quad
.IsRectilinear() ||
723 !device_quad
.BoundingBox().IsExpressibleAsRect());
725 device_layer_bounds
.InflateAntiAliasingDistance();
726 device_layer_edges
.InflateAntiAliasingDistance();
729 scoped_ptr
<ResourceProvider::ScopedReadLockGL
> mask_resource_lock
;
730 unsigned mask_texture_id
= 0;
731 if (quad
->mask_resource_id
) {
732 mask_resource_lock
.reset(new ResourceProvider::ScopedReadLockGL(
733 resource_provider_
, quad
->mask_resource_id
));
734 mask_texture_id
= mask_resource_lock
->texture_id();
737 // FIXME: use the background_texture and blend the background in with this
738 // draw instead of having a separate copy of the background texture.
740 scoped_ptr
<ResourceProvider::ScopedReadLockGL
> contents_resource_lock
;
741 if (filter_bitmap
.getTexture()) {
743 reinterpret_cast<GrTexture
*>(filter_bitmap
.getTexture());
744 Context()->bindTexture(GL_TEXTURE_2D
, texture
->getTextureHandle());
746 contents_resource_lock
= make_scoped_ptr(
747 new ResourceProvider::ScopedSamplerGL(resource_provider_
,
748 contents_texture
->id(),
753 TexCoordPrecision texCoordPrecision
= TexCoordPrecisionRequired(
754 context_
, highp_threshold_min_
,
755 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
757 int shader_quad_location
= -1;
758 int shader_edge_location
= -1;
759 int shader_mask_sampler_location
= -1;
760 int shader_mask_tex_coord_scale_location
= -1;
761 int shader_mask_tex_coord_offset_location
= -1;
762 int shader_matrix_location
= -1;
763 int shader_alpha_location
= -1;
764 int shader_color_matrix_location
= -1;
765 int shader_color_offset_location
= -1;
766 int shader_tex_transform_location
= -1;
767 int shader_tex_scale_location
= -1;
769 if (use_aa
&& mask_texture_id
&& !use_color_matrix
) {
770 const RenderPassMaskProgramAA
* program
=
771 GetRenderPassMaskProgramAA(texCoordPrecision
);
772 SetUseProgram(program
->program());
774 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
776 shader_quad_location
= program
->vertex_shader().point_location();
777 shader_edge_location
= program
->fragment_shader().edge_location();
778 shader_mask_sampler_location
=
779 program
->fragment_shader().mask_sampler_location();
780 shader_mask_tex_coord_scale_location
=
781 program
->fragment_shader().mask_tex_coord_scale_location();
782 shader_mask_tex_coord_offset_location
=
783 program
->fragment_shader().mask_tex_coord_offset_location();
784 shader_matrix_location
= program
->vertex_shader().matrix_location();
785 shader_alpha_location
= program
->fragment_shader().alpha_location();
786 shader_tex_scale_location
= program
->vertex_shader().tex_scale_location();
787 } else if (!use_aa
&& mask_texture_id
&& !use_color_matrix
) {
788 const RenderPassMaskProgram
* program
=
789 GetRenderPassMaskProgram(texCoordPrecision
);
790 SetUseProgram(program
->program());
792 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
794 shader_mask_sampler_location
=
795 program
->fragment_shader().mask_sampler_location();
796 shader_mask_tex_coord_scale_location
=
797 program
->fragment_shader().mask_tex_coord_scale_location();
798 shader_mask_tex_coord_offset_location
=
799 program
->fragment_shader().mask_tex_coord_offset_location();
800 shader_matrix_location
= program
->vertex_shader().matrix_location();
801 shader_alpha_location
= program
->fragment_shader().alpha_location();
802 shader_tex_transform_location
=
803 program
->vertex_shader().tex_transform_location();
804 } else if (use_aa
&& !mask_texture_id
&& !use_color_matrix
) {
805 const RenderPassProgramAA
* program
=
806 GetRenderPassProgramAA(texCoordPrecision
);
807 SetUseProgram(program
->program());
809 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
811 shader_quad_location
= program
->vertex_shader().point_location();
812 shader_edge_location
= program
->fragment_shader().edge_location();
813 shader_matrix_location
= program
->vertex_shader().matrix_location();
814 shader_alpha_location
= program
->fragment_shader().alpha_location();
815 shader_tex_scale_location
= program
->vertex_shader().tex_scale_location();
816 } else if (use_aa
&& mask_texture_id
&& use_color_matrix
) {
817 const RenderPassMaskColorMatrixProgramAA
* program
=
818 GetRenderPassMaskColorMatrixProgramAA(texCoordPrecision
);
819 SetUseProgram(program
->program());
821 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
823 shader_matrix_location
= program
->vertex_shader().matrix_location();
824 shader_quad_location
= program
->vertex_shader().point_location();
825 shader_tex_scale_location
= program
->vertex_shader().tex_scale_location();
826 shader_edge_location
= program
->fragment_shader().edge_location();
827 shader_alpha_location
= program
->fragment_shader().alpha_location();
828 shader_mask_sampler_location
=
829 program
->fragment_shader().mask_sampler_location();
830 shader_mask_tex_coord_scale_location
=
831 program
->fragment_shader().mask_tex_coord_scale_location();
832 shader_mask_tex_coord_offset_location
=
833 program
->fragment_shader().mask_tex_coord_offset_location();
834 shader_color_matrix_location
=
835 program
->fragment_shader().color_matrix_location();
836 shader_color_offset_location
=
837 program
->fragment_shader().color_offset_location();
838 } else if (use_aa
&& !mask_texture_id
&& use_color_matrix
) {
839 const RenderPassColorMatrixProgramAA
* program
=
840 GetRenderPassColorMatrixProgramAA(texCoordPrecision
);
841 SetUseProgram(program
->program());
843 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
845 shader_matrix_location
= program
->vertex_shader().matrix_location();
846 shader_quad_location
= program
->vertex_shader().point_location();
847 shader_tex_scale_location
= program
->vertex_shader().tex_scale_location();
848 shader_edge_location
= program
->fragment_shader().edge_location();
849 shader_alpha_location
= program
->fragment_shader().alpha_location();
850 shader_color_matrix_location
=
851 program
->fragment_shader().color_matrix_location();
852 shader_color_offset_location
=
853 program
->fragment_shader().color_offset_location();
854 } else if (!use_aa
&& mask_texture_id
&& use_color_matrix
) {
855 const RenderPassMaskColorMatrixProgram
* program
=
856 GetRenderPassMaskColorMatrixProgram(texCoordPrecision
);
857 SetUseProgram(program
->program());
859 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
861 shader_matrix_location
= program
->vertex_shader().matrix_location();
862 shader_tex_transform_location
=
863 program
->vertex_shader().tex_transform_location();
864 shader_mask_sampler_location
=
865 program
->fragment_shader().mask_sampler_location();
866 shader_mask_tex_coord_scale_location
=
867 program
->fragment_shader().mask_tex_coord_scale_location();
868 shader_mask_tex_coord_offset_location
=
869 program
->fragment_shader().mask_tex_coord_offset_location();
870 shader_alpha_location
= program
->fragment_shader().alpha_location();
871 shader_color_matrix_location
=
872 program
->fragment_shader().color_matrix_location();
873 shader_color_offset_location
=
874 program
->fragment_shader().color_offset_location();
875 } else if (!use_aa
&& !mask_texture_id
&& use_color_matrix
) {
876 const RenderPassColorMatrixProgram
* program
=
877 GetRenderPassColorMatrixProgram(texCoordPrecision
);
878 SetUseProgram(program
->program());
880 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
882 shader_matrix_location
= program
->vertex_shader().matrix_location();
883 shader_tex_transform_location
=
884 program
->vertex_shader().tex_transform_location();
885 shader_alpha_location
= program
->fragment_shader().alpha_location();
886 shader_color_matrix_location
=
887 program
->fragment_shader().color_matrix_location();
888 shader_color_offset_location
=
889 program
->fragment_shader().color_offset_location();
891 const RenderPassProgram
* program
=
892 GetRenderPassProgram(texCoordPrecision
);
893 SetUseProgram(program
->program());
895 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
897 shader_matrix_location
= program
->vertex_shader().matrix_location();
898 shader_alpha_location
= program
->fragment_shader().alpha_location();
899 shader_tex_transform_location
=
900 program
->vertex_shader().tex_transform_location();
903 quad
->rect
.width() / static_cast<float>(contents_texture
->size().width());
904 float tex_scale_y
= quad
->rect
.height() /
905 static_cast<float>(contents_texture
->size().height());
906 DCHECK_LE(tex_scale_x
, 1.0f
);
907 DCHECK_LE(tex_scale_y
, 1.0f
);
909 if (shader_tex_transform_location
!= -1) {
911 Context()->uniform4f(shader_tex_transform_location
,
916 } else if (shader_tex_scale_location
!= -1) {
918 Context()->uniform2f(
919 shader_tex_scale_location
, tex_scale_x
, tex_scale_y
));
921 DCHECK(IsContextLost());
924 if (shader_mask_sampler_location
!= -1) {
925 DCHECK_NE(shader_mask_tex_coord_scale_location
, 1);
926 DCHECK_NE(shader_mask_tex_coord_offset_location
, 1);
927 GLC(Context(), Context()->activeTexture(GL_TEXTURE1
));
928 GLC(Context(), Context()->uniform1i(shader_mask_sampler_location
, 1));
930 Context()->uniform2f(shader_mask_tex_coord_offset_location
,
931 quad
->mask_uv_rect
.x(),
932 quad
->mask_uv_rect
.y()));
934 Context()->uniform2f(shader_mask_tex_coord_scale_location
,
935 quad
->mask_uv_rect
.width() / tex_scale_x
,
936 quad
->mask_uv_rect
.height() / tex_scale_y
));
937 resource_provider_
->BindForSampling(
938 quad
->mask_resource_id
, GL_TEXTURE_2D
, GL_LINEAR
);
939 GLC(Context(), Context()->activeTexture(GL_TEXTURE0
));
942 if (shader_edge_location
!= -1) {
944 device_layer_edges
.ToFloatArray(edge
);
945 device_layer_bounds
.ToFloatArray(&edge
[12]);
946 GLC(Context(), Context()->uniform3fv(shader_edge_location
, 8, edge
));
949 if (shader_color_matrix_location
!= -1) {
951 for (int i
= 0; i
< 4; ++i
) {
952 for (int j
= 0; j
< 4; ++j
)
953 matrix
[i
* 4 + j
] = SkScalarToFloat(color_matrix
[j
* 5 + i
]);
956 Context()->uniformMatrix4fv(
957 shader_color_matrix_location
, 1, false, matrix
));
959 static const float kScale
= 1.0f
/ 255.0f
;
960 if (shader_color_offset_location
!= -1) {
962 for (int i
= 0; i
< 4; ++i
)
963 offset
[i
] = SkScalarToFloat(color_matrix
[i
* 5 + 4]) * kScale
;
966 Context()->uniform4fv(shader_color_offset_location
, 1, offset
));
969 // Map device space quad to surface space. contents_device_transform has no 3d
970 // component since it was flattened, so we don't need to project.
971 gfx::QuadF surface_quad
= MathUtil::MapQuad(contents_device_transform_inverse
,
972 device_layer_edges
.ToQuadF(),
976 SetShaderOpacity(quad
->opacity(), shader_alpha_location
);
977 SetShaderQuadF(surface_quad
, shader_quad_location
);
979 frame
, quad
->quadTransform(), quad
->rect
, shader_matrix_location
);
981 // Flush the compositor context before the filter bitmap goes out of
982 // scope, so the draw gets processed before the filter texture gets deleted.
983 if (filter_bitmap
.getTexture())
987 struct SolidColorProgramUniforms
{
989 unsigned matrix_location
;
990 unsigned color_location
;
991 unsigned point_location
;
992 unsigned tex_scale_location
;
993 unsigned edge_location
;
997 static void SolidColorUniformLocation(T program
,
998 SolidColorProgramUniforms
* uniforms
) {
999 uniforms
->program
= program
->program();
1000 uniforms
->matrix_location
= program
->vertex_shader().matrix_location();
1001 uniforms
->color_location
= program
->fragment_shader().color_location();
1002 uniforms
->point_location
= program
->vertex_shader().point_location();
1003 uniforms
->tex_scale_location
= program
->vertex_shader().tex_scale_location();
1004 uniforms
->edge_location
= program
->fragment_shader().edge_location();
1007 bool GLRenderer::SetupQuadForAntialiasing(
1008 const gfx::Transform
& device_transform
,
1009 const DrawQuad
* quad
,
1010 gfx::QuadF
* local_quad
,
1011 float edge
[24]) const {
1012 gfx::Rect tile_rect
= quad
->visible_rect
;
1014 bool clipped
= false;
1015 gfx::QuadF device_layer_quad
= MathUtil::MapQuad(
1016 device_transform
, gfx::QuadF(quad
->visibleContentRect()), &clipped
);
1019 // TODO(reveman): Axis-aligned is not enough to avoid anti-aliasing.
1020 // Bounding rectangle for quad also needs to be expressible as an integer
1021 // rectangle. crbug.com/169374
1022 bool is_axis_aligned_in_target
= device_layer_quad
.IsRectilinear();
1023 bool use_aa
= !clipped
&& !is_axis_aligned_in_target
&& quad
->IsEdge();
1028 LayerQuad
device_layer_bounds(gfx::QuadF(device_layer_quad
.BoundingBox()));
1029 device_layer_bounds
.InflateAntiAliasingDistance();
1031 LayerQuad
device_layer_edges(device_layer_quad
);
1032 device_layer_edges
.InflateAntiAliasingDistance();
1034 device_layer_edges
.ToFloatArray(edge
);
1035 device_layer_bounds
.ToFloatArray(&edge
[12]);
1037 gfx::PointF bottom_right
= tile_rect
.bottom_right();
1038 gfx::PointF bottom_left
= tile_rect
.bottom_left();
1039 gfx::PointF top_left
= tile_rect
.origin();
1040 gfx::PointF top_right
= tile_rect
.top_right();
1042 // Map points to device space.
1043 bottom_right
= MathUtil::MapPoint(device_transform
, bottom_right
, &clipped
);
1045 bottom_left
= MathUtil::MapPoint(device_transform
, bottom_left
, &clipped
);
1047 top_left
= MathUtil::MapPoint(device_transform
, top_left
, &clipped
);
1049 top_right
= MathUtil::MapPoint(device_transform
, top_right
, &clipped
);
1052 LayerQuad::Edge
bottom_edge(bottom_right
, bottom_left
);
1053 LayerQuad::Edge
left_edge(bottom_left
, top_left
);
1054 LayerQuad::Edge
top_edge(top_left
, top_right
);
1055 LayerQuad::Edge
right_edge(top_right
, bottom_right
);
1057 // Only apply anti-aliasing to edges not clipped by culling or scissoring.
1058 if (quad
->IsTopEdge() && tile_rect
.y() == quad
->rect
.y())
1059 top_edge
= device_layer_edges
.top();
1060 if (quad
->IsLeftEdge() && tile_rect
.x() == quad
->rect
.x())
1061 left_edge
= device_layer_edges
.left();
1062 if (quad
->IsRightEdge() && tile_rect
.right() == quad
->rect
.right())
1063 right_edge
= device_layer_edges
.right();
1064 if (quad
->IsBottomEdge() && tile_rect
.bottom() == quad
->rect
.bottom())
1065 bottom_edge
= device_layer_edges
.bottom();
1067 float sign
= gfx::QuadF(tile_rect
).IsCounterClockwise() ? -1 : 1;
1068 bottom_edge
.scale(sign
);
1069 left_edge
.scale(sign
);
1070 top_edge
.scale(sign
);
1071 right_edge
.scale(sign
);
1073 // Create device space quad.
1074 LayerQuad
device_quad(left_edge
, top_edge
, right_edge
, bottom_edge
);
1076 // Map device space quad to local space. device_transform has no 3d
1077 // component since it was flattened, so we don't need to project. We should
1078 // have already checked that the transform was uninvertible above.
1079 gfx::Transform
inverse_device_transform(
1080 gfx::Transform::kSkipInitialization
);
1081 bool did_invert
= device_transform
.GetInverse(&inverse_device_transform
);
1083 *local_quad
= MathUtil::MapQuad(
1084 inverse_device_transform
, device_quad
.ToQuadF(), &clipped
);
1085 // We should not DCHECK(!clipped) here, because anti-aliasing inflation may
1086 // cause device_quad to become clipped. To our knowledge this scenario does
1087 // not need to be handled differently than the unclipped case.
1092 void GLRenderer::DrawSolidColorQuad(const DrawingFrame
* frame
,
1093 const SolidColorDrawQuad
* quad
) {
1094 SetBlendEnabled(quad
->ShouldDrawWithBlending());
1095 gfx::Rect tile_rect
= quad
->visible_rect
;
1097 gfx::Transform device_transform
=
1098 frame
->window_matrix
* frame
->projection_matrix
* quad
->quadTransform();
1099 device_transform
.FlattenTo2d();
1100 if (!device_transform
.IsInvertible())
1103 gfx::QuadF local_quad
= gfx::QuadF(gfx::RectF(tile_rect
));
1105 bool use_aa
= SetupQuadForAntialiasing(
1106 device_transform
, quad
, &local_quad
, edge
);
1108 SolidColorProgramUniforms uniforms
;
1110 SolidColorUniformLocation(GetSolidColorProgramAA(), &uniforms
);
1112 SolidColorUniformLocation(GetSolidColorProgram(), &uniforms
);
1113 SetUseProgram(uniforms
.program
);
1115 SkColor color
= quad
->color
;
1116 float opacity
= quad
->opacity();
1117 float alpha
= (SkColorGetA(color
) * (1.0f
/ 255.0f
)) * opacity
;
1120 Context()->uniform4f(uniforms
.color_location
,
1121 (SkColorGetR(color
) * (1.0f
/ 255.0f
)) * alpha
,
1122 (SkColorGetG(color
) * (1.0f
/ 255.0f
)) * alpha
,
1123 (SkColorGetB(color
) * (1.0f
/ 255.0f
)) * alpha
,
1127 GLC(Context(), Context()->uniform3fv(uniforms
.edge_location
, 8, edge
));
1129 // Enable blending when the quad properties require it or if we decided
1130 // to use antialiasing.
1131 SetBlendEnabled(quad
->ShouldDrawWithBlending() || use_aa
);
1133 // Normalize to tile_rect.
1134 local_quad
.Scale(1.0f
/ tile_rect
.width(), 1.0f
/ tile_rect
.height());
1136 SetShaderQuadF(local_quad
, uniforms
.point_location
);
1138 // The transform and vertex data are used to figure out the extents that the
1139 // un-antialiased quad should have and which vertex this is and the float
1140 // quad passed in via uniform is the actual geometry that gets used to draw
1141 // it. This is why this centered rect is used and not the original quad_rect.
1142 gfx::RectF
centered_rect(gfx::PointF(-0.5f
* tile_rect
.width(),
1143 -0.5f
* tile_rect
.height()),
1145 DrawQuadGeometry(frame
, quad
->quadTransform(),
1146 centered_rect
, uniforms
.matrix_location
);
1149 struct TileProgramUniforms
{
1151 unsigned sampler_location
;
1152 unsigned vertex_tex_transform_location
;
1153 unsigned fragment_tex_transform_location
;
1154 unsigned edge_location
;
1155 unsigned matrix_location
;
1156 unsigned alpha_location
;
1157 unsigned point_location
;
1161 static void TileUniformLocation(T program
, TileProgramUniforms
* uniforms
) {
1162 uniforms
->program
= program
->program();
1163 uniforms
->vertex_tex_transform_location
=
1164 program
->vertex_shader().vertex_tex_transform_location();
1165 uniforms
->matrix_location
= program
->vertex_shader().matrix_location();
1166 uniforms
->point_location
= program
->vertex_shader().point_location();
1168 uniforms
->sampler_location
= program
->fragment_shader().sampler_location();
1169 uniforms
->alpha_location
= program
->fragment_shader().alpha_location();
1170 uniforms
->fragment_tex_transform_location
=
1171 program
->fragment_shader().fragment_tex_transform_location();
1172 uniforms
->edge_location
= program
->fragment_shader().edge_location();
1175 void GLRenderer::DrawTileQuad(const DrawingFrame
* frame
,
1176 const TileDrawQuad
* quad
) {
1177 DrawContentQuad(frame
, quad
, quad
->resource_id
);
1180 void GLRenderer::DrawContentQuad(const DrawingFrame
* frame
,
1181 const ContentDrawQuadBase
* quad
,
1182 ResourceProvider::ResourceId resource_id
) {
1183 gfx::Rect tile_rect
= quad
->visible_rect
;
1185 gfx::RectF tex_coord_rect
= quad
->tex_coord_rect
;
1186 float tex_to_geom_scale_x
= quad
->rect
.width() / tex_coord_rect
.width();
1187 float tex_to_geom_scale_y
= quad
->rect
.height() / tex_coord_rect
.height();
1189 // tex_coord_rect corresponds to quad_rect, but quad_visible_rect may be
1190 // smaller than quad_rect due to occlusion or clipping. Adjust
1191 // tex_coord_rect to match.
1192 gfx::Vector2d top_left_diff
= tile_rect
.origin() - quad
->rect
.origin();
1193 gfx::Vector2d bottom_right_diff
=
1194 tile_rect
.bottom_right() - quad
->rect
.bottom_right();
1195 tex_coord_rect
.Inset(top_left_diff
.x() / tex_to_geom_scale_x
,
1196 top_left_diff
.y() / tex_to_geom_scale_y
,
1197 -bottom_right_diff
.x() / tex_to_geom_scale_x
,
1198 -bottom_right_diff
.y() / tex_to_geom_scale_y
);
1200 gfx::RectF
clamp_geom_rect(tile_rect
);
1201 gfx::RectF
clamp_tex_rect(tex_coord_rect
);
1202 // Clamp texture coordinates to avoid sampling outside the layer
1203 // by deflating the tile region half a texel or half a texel
1204 // minus epsilon for one pixel layers. The resulting clamp region
1205 // is mapped to the unit square by the vertex shader and mapped
1206 // back to normalized texture coordinates by the fragment shader
1207 // after being clamped to 0-1 range.
1208 const float epsilon
= 1.0f
/ 1024.0f
;
1209 float tex_clamp_x
= std::min(0.5f
, 0.5f
* clamp_tex_rect
.width() - epsilon
);
1210 float tex_clamp_y
= std::min(0.5f
, 0.5f
* clamp_tex_rect
.height() - epsilon
);
1211 float geom_clamp_x
= std::min(tex_clamp_x
* tex_to_geom_scale_x
,
1212 0.5f
* clamp_geom_rect
.width() - epsilon
);
1213 float geom_clamp_y
= std::min(tex_clamp_y
* tex_to_geom_scale_y
,
1214 0.5f
* clamp_geom_rect
.height() - epsilon
);
1215 clamp_geom_rect
.Inset(geom_clamp_x
, geom_clamp_y
, geom_clamp_x
, geom_clamp_y
);
1216 clamp_tex_rect
.Inset(tex_clamp_x
, tex_clamp_y
, tex_clamp_x
, tex_clamp_y
);
1218 // Map clamping rectangle to unit square.
1219 float vertex_tex_translate_x
= -clamp_geom_rect
.x() / clamp_geom_rect
.width();
1220 float vertex_tex_translate_y
=
1221 -clamp_geom_rect
.y() / clamp_geom_rect
.height();
1222 float vertex_tex_scale_x
= tile_rect
.width() / clamp_geom_rect
.width();
1223 float vertex_tex_scale_y
= tile_rect
.height() / clamp_geom_rect
.height();
1225 // We assume we do not need highp texture coordinates for tiles.
1226 // Make sure that assumption is correct here.
1227 DCHECK_EQ(TexCoordPrecisionMedium
, TexCoordPrecisionRequired(
1228 context_
, highp_threshold_min_
, quad
->texture_size
));
1230 // Map to normalized texture coordinates.
1231 gfx::Size texture_size
= quad
->texture_size
;
1232 float fragment_tex_translate_x
= clamp_tex_rect
.x() / texture_size
.width();
1233 float fragment_tex_translate_y
= clamp_tex_rect
.y() / texture_size
.height();
1234 float fragment_tex_scale_x
= clamp_tex_rect
.width() / texture_size
.width();
1235 float fragment_tex_scale_y
= clamp_tex_rect
.height() / texture_size
.height();
1237 gfx::Transform device_transform
=
1238 frame
->window_matrix
* frame
->projection_matrix
* quad
->quadTransform();
1239 device_transform
.FlattenTo2d();
1240 if (!device_transform
.IsInvertible())
1243 gfx::QuadF local_quad
= gfx::QuadF(gfx::RectF(tile_rect
));
1245 bool use_aa
= SetupQuadForAntialiasing(
1246 device_transform
, quad
, &local_quad
, edge
);
1248 TileProgramUniforms uniforms
;
1250 if (quad
->swizzle_contents
)
1251 TileUniformLocation(GetTileProgramSwizzleAA(), &uniforms
);
1253 TileUniformLocation(GetTileProgramAA(), &uniforms
);
1255 if (quad
->ShouldDrawWithBlending()) {
1256 if (quad
->swizzle_contents
)
1257 TileUniformLocation(GetTileProgramSwizzle(), &uniforms
);
1259 TileUniformLocation(GetTileProgram(), &uniforms
);
1261 if (quad
->swizzle_contents
)
1262 TileUniformLocation(GetTileProgramSwizzleOpaque(), &uniforms
);
1264 TileUniformLocation(GetTileProgramOpaque(), &uniforms
);
1268 SetUseProgram(uniforms
.program
);
1269 GLC(Context(), Context()->uniform1i(uniforms
.sampler_location
, 0));
1270 bool scaled
= (tex_to_geom_scale_x
!= 1.f
|| tex_to_geom_scale_y
!= 1.f
);
1271 GLenum filter
= (use_aa
|| scaled
||
1272 !quad
->quadTransform().IsIdentityOrIntegerTranslation())
1275 ResourceProvider::ScopedSamplerGL
quad_resource_lock(
1276 resource_provider_
, resource_id
, GL_TEXTURE_2D
, filter
);
1279 GLC(Context(), Context()->uniform3fv(uniforms
.edge_location
, 8, edge
));
1282 Context()->uniform4f(uniforms
.vertex_tex_transform_location
,
1283 vertex_tex_translate_x
,
1284 vertex_tex_translate_y
,
1286 vertex_tex_scale_y
));
1288 Context()->uniform4f(uniforms
.fragment_tex_transform_location
,
1289 fragment_tex_translate_x
,
1290 fragment_tex_translate_y
,
1291 fragment_tex_scale_x
,
1292 fragment_tex_scale_y
));
1294 // Move fragment shader transform to vertex shader. We can do this while
1295 // still producing correct results as fragment_tex_transform_location
1296 // should always be non-negative when tiles are transformed in a way
1297 // that could result in sampling outside the layer.
1298 vertex_tex_scale_x
*= fragment_tex_scale_x
;
1299 vertex_tex_scale_y
*= fragment_tex_scale_y
;
1300 vertex_tex_translate_x
*= fragment_tex_scale_x
;
1301 vertex_tex_translate_y
*= fragment_tex_scale_y
;
1302 vertex_tex_translate_x
+= fragment_tex_translate_x
;
1303 vertex_tex_translate_y
+= fragment_tex_translate_y
;
1306 Context()->uniform4f(uniforms
.vertex_tex_transform_location
,
1307 vertex_tex_translate_x
,
1308 vertex_tex_translate_y
,
1310 vertex_tex_scale_y
));
1313 // Enable blending when the quad properties require it or if we decided
1314 // to use antialiasing.
1315 SetBlendEnabled(quad
->ShouldDrawWithBlending() || use_aa
);
1317 // Normalize to tile_rect.
1318 local_quad
.Scale(1.0f
/ tile_rect
.width(), 1.0f
/ tile_rect
.height());
1320 SetShaderOpacity(quad
->opacity(), uniforms
.alpha_location
);
1321 SetShaderQuadF(local_quad
, uniforms
.point_location
);
1323 // The transform and vertex data are used to figure out the extents that the
1324 // un-antialiased quad should have and which vertex this is and the float
1325 // quad passed in via uniform is the actual geometry that gets used to draw
1326 // it. This is why this centered rect is used and not the original quad_rect.
1327 gfx::RectF
centered_rect(
1328 gfx::PointF(-0.5f
* tile_rect
.width(), -0.5f
* tile_rect
.height()),
1331 frame
, quad
->quadTransform(), centered_rect
, uniforms
.matrix_location
);
1334 void GLRenderer::DrawYUVVideoQuad(const DrawingFrame
* frame
,
1335 const YUVVideoDrawQuad
* quad
) {
1336 SetBlendEnabled(quad
->ShouldDrawWithBlending());
1338 TexCoordPrecision texCoordPrecision
= TexCoordPrecisionRequired(
1339 context_
, highp_threshold_min_
,
1340 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1342 const VideoYUVProgram
* program
= GetVideoYUVProgram(texCoordPrecision
);
1343 DCHECK(program
&& (program
->initialized() || IsContextLost()));
1345 GLC(Context(), Context()->activeTexture(GL_TEXTURE1
));
1346 ResourceProvider::ScopedSamplerGL
y_plane_lock(
1347 resource_provider_
, quad
->y_plane_resource_id
, GL_TEXTURE_2D
, GL_LINEAR
);
1348 GLC(Context(), Context()->activeTexture(GL_TEXTURE2
));
1349 ResourceProvider::ScopedSamplerGL
u_plane_lock(
1350 resource_provider_
, quad
->u_plane_resource_id
, GL_TEXTURE_2D
, GL_LINEAR
);
1351 GLC(Context(), Context()->activeTexture(GL_TEXTURE3
));
1352 ResourceProvider::ScopedSamplerGL
v_plane_lock(
1353 resource_provider_
, quad
->v_plane_resource_id
, GL_TEXTURE_2D
, GL_LINEAR
);
1355 SetUseProgram(program
->program());
1358 Context()->uniform2f(program
->vertex_shader().tex_scale_location(),
1359 quad
->tex_scale
.width(),
1360 quad
->tex_scale
.height()));
1362 Context()->uniform1i(program
->fragment_shader().y_texture_location(), 1));
1364 Context()->uniform1i(program
->fragment_shader().u_texture_location(), 2));
1366 Context()->uniform1i(program
->fragment_shader().v_texture_location(), 3));
1368 // These values are magic numbers that are used in the transformation from YUV
1369 // to RGB color values. They are taken from the following webpage:
1370 // http://www.fourcc.org/fccyvrgb.php
1371 float yuv_to_rgb
[9] = {
1372 1.164f
, 1.164f
, 1.164f
,
1373 0.0f
, -.391f
, 2.018f
,
1374 1.596f
, -.813f
, 0.0f
,
1377 Context()->uniformMatrix3fv(
1378 program
->fragment_shader().yuv_matrix_location(), 1, 0, yuv_to_rgb
));
1380 // These values map to 16, 128, and 128 respectively, and are computed
1381 // as a fraction over 256 (e.g. 16 / 256 = 0.0625).
1382 // They are used in the YUV to RGBA conversion formula:
1383 // Y - 16 : Gives 16 values of head and footroom for overshooting
1384 // U - 128 : Turns unsigned U into signed U [-128,127]
1385 // V - 128 : Turns unsigned V into signed V [-128,127]
1386 float yuv_adjust
[3] = { -0.0625f
, -0.5f
, -0.5f
, };
1388 Context()->uniform3fv(
1389 program
->fragment_shader().yuv_adj_location(), 1, yuv_adjust
));
1391 SetShaderOpacity(quad
->opacity(),
1392 program
->fragment_shader().alpha_location());
1393 DrawQuadGeometry(frame
,
1394 quad
->quadTransform(),
1396 program
->vertex_shader().matrix_location());
1398 // Reset active texture back to texture 0.
1399 GLC(Context(), Context()->activeTexture(GL_TEXTURE0
));
1402 void GLRenderer::DrawStreamVideoQuad(const DrawingFrame
* frame
,
1403 const StreamVideoDrawQuad
* quad
) {
1404 SetBlendEnabled(quad
->ShouldDrawWithBlending());
1406 static float gl_matrix
[16];
1408 DCHECK(capabilities_
.using_egl_image
);
1410 TexCoordPrecision texCoordPrecision
= TexCoordPrecisionRequired(
1411 context_
, highp_threshold_min_
,
1412 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1414 const VideoStreamTextureProgram
* program
=
1415 GetVideoStreamTextureProgram(texCoordPrecision
);
1416 SetUseProgram(program
->program());
1418 ToGLMatrix(&gl_matrix
[0], quad
->matrix
);
1420 Context()->uniformMatrix4fv(
1421 program
->vertex_shader().tex_matrix_location(), 1, false, gl_matrix
));
1423 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
,
1426 Context()->bindTexture(GL_TEXTURE_EXTERNAL_OES
, lock
.texture_id()));
1429 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
1431 SetShaderOpacity(quad
->opacity(),
1432 program
->fragment_shader().alpha_location());
1433 DrawQuadGeometry(frame
,
1434 quad
->quadTransform(),
1436 program
->vertex_shader().matrix_location());
1439 void GLRenderer::DrawPictureQuad(const DrawingFrame
* frame
,
1440 const PictureDrawQuad
* quad
) {
1441 if (on_demand_tile_raster_bitmap_
.width() != quad
->texture_size
.width() ||
1442 on_demand_tile_raster_bitmap_
.height() != quad
->texture_size
.height()) {
1443 on_demand_tile_raster_bitmap_
.setConfig(
1444 SkBitmap::kARGB_8888_Config
,
1445 quad
->texture_size
.width(),
1446 quad
->texture_size
.height());
1447 on_demand_tile_raster_bitmap_
.allocPixels();
1449 if (on_demand_tile_raster_resource_id_
)
1450 resource_provider_
->DeleteResource(on_demand_tile_raster_resource_id_
);
1452 on_demand_tile_raster_resource_id_
= resource_provider_
->CreateGLTexture(
1455 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
1456 ResourceProvider::TextureUsageAny
);
1459 SkDevice
device(on_demand_tile_raster_bitmap_
);
1460 SkCanvas
canvas(&device
);
1462 quad
->picture_pile
->Raster(&canvas
, quad
->content_rect
, quad
->contents_scale
);
1464 resource_provider_
->SetPixels(
1465 on_demand_tile_raster_resource_id_
,
1466 reinterpret_cast<uint8_t*>(on_demand_tile_raster_bitmap_
.getPixels()),
1467 gfx::Rect(quad
->texture_size
),
1468 gfx::Rect(quad
->texture_size
),
1471 DrawContentQuad(frame
, quad
, on_demand_tile_raster_resource_id_
);
1474 struct TextureProgramBinding
{
1475 template <class Program
>
1476 void Set(Program
* program
, WebKit::WebGraphicsContext3D
* context
) {
1477 DCHECK(program
&& (program
->initialized() || context
->isContextLost()));
1478 program_id
= program
->program();
1479 sampler_location
= program
->fragment_shader().sampler_location();
1480 matrix_location
= program
->vertex_shader().matrix_location();
1481 alpha_location
= program
->fragment_shader().alpha_location();
1484 int sampler_location
;
1485 int matrix_location
;
1489 struct TexTransformTextureProgramBinding
: TextureProgramBinding
{
1490 template <class Program
>
1491 void Set(Program
* program
, WebKit::WebGraphicsContext3D
* context
) {
1492 TextureProgramBinding::Set(program
, context
);
1493 tex_transform_location
= program
->vertex_shader().tex_transform_location();
1494 vertex_opacity_location
=
1495 program
->vertex_shader().vertex_opacity_location();
1497 int tex_transform_location
;
1498 int vertex_opacity_location
;
1501 void GLRenderer::FlushTextureQuadCache() {
1502 // Check to see if we have anything to draw.
1503 if (draw_cache_
.program_id
== 0)
1506 // Set the correct blending mode.
1507 SetBlendEnabled(draw_cache_
.needs_blending
);
1509 // Bind the program to the GL state.
1510 SetUseProgram(draw_cache_
.program_id
);
1512 // Bind the correct texture sampler location.
1513 GLC(Context(), Context()->uniform1i(draw_cache_
.sampler_location
, 0));
1515 // Assume the current active textures is 0.
1516 ResourceProvider::ScopedReadLockGL
locked_quad(resource_provider_
,
1517 draw_cache_
.resource_id
);
1519 Context()->bindTexture(GL_TEXTURE_2D
, locked_quad
.texture_id()));
1521 // set up premultiplied alpha.
1522 if (!draw_cache_
.use_premultiplied_alpha
) {
1523 // As it turns out, the premultiplied alpha blending function (ONE,
1524 // ONE_MINUS_SRC_ALPHA) will never cause the alpha channel to be set to
1525 // anything less than 1.0f if it is initialized to that value! Therefore,
1526 // premultiplied_alpha being false is the first situation we can generally
1527 // see an alpha channel less than 1.0f coming out of the compositor. This is
1528 // causing platform differences in some layout tests (see
1529 // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use
1530 // a separate blend function for the alpha channel to avoid modifying it.
1531 // Don't use colorMask() for this as it has performance implications on some
1534 Context()->blendFuncSeparate(
1535 GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
, GL_ZERO
, GL_ONE
));
1539 sizeof(Float4
) == 4 * sizeof(float), // NOLINT(runtime/sizeof)
1540 struct_is_densely_packed
);
1542 sizeof(Float16
) == 16 * sizeof(float), // NOLINT(runtime/sizeof)
1543 struct_is_densely_packed
);
1545 // Upload the tranforms for both points and uvs.
1547 context_
->uniformMatrix4fv(
1548 static_cast<int>(draw_cache_
.matrix_location
),
1549 static_cast<int>(draw_cache_
.matrix_data
.size()),
1551 reinterpret_cast<float*>(&draw_cache_
.matrix_data
.front())));
1553 context_
->uniform4fv(
1554 static_cast<int>(draw_cache_
.uv_xform_location
),
1555 static_cast<int>(draw_cache_
.uv_xform_data
.size()),
1556 reinterpret_cast<float*>(&draw_cache_
.uv_xform_data
.front())));
1558 context_
->uniform1fv(
1559 static_cast<int>(draw_cache_
.vertex_opacity_location
),
1560 static_cast<int>(draw_cache_
.vertex_opacity_data
.size()),
1561 static_cast<float*>(&draw_cache_
.vertex_opacity_data
.front())));
1565 context_
->drawElements(GL_TRIANGLES
,
1566 6 * draw_cache_
.matrix_data
.size(),
1570 // Clean up after ourselves (reset state set above).
1571 if (!draw_cache_
.use_premultiplied_alpha
)
1572 GLC(context_
, context_
->blendFunc(GL_ONE
, GL_ONE_MINUS_SRC_ALPHA
));
1575 draw_cache_
.program_id
= 0;
1576 draw_cache_
.uv_xform_data
.resize(0);
1577 draw_cache_
.vertex_opacity_data
.resize(0);
1578 draw_cache_
.matrix_data
.resize(0);
1581 void GLRenderer::EnqueueTextureQuad(const DrawingFrame
* frame
,
1582 const TextureDrawQuad
* quad
) {
1583 TexCoordPrecision texCoordPrecision
= TexCoordPrecisionRequired(
1584 context_
, highp_threshold_min_
,
1585 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1587 // Choose the correct texture program binding
1588 TexTransformTextureProgramBinding binding
;
1590 binding
.Set(GetTextureProgramFlip(texCoordPrecision
), Context());
1592 binding
.Set(GetTextureProgram(texCoordPrecision
), Context());
1594 int resource_id
= quad
->resource_id
;
1596 if (draw_cache_
.program_id
!= binding
.program_id
||
1597 draw_cache_
.resource_id
!= resource_id
||
1598 draw_cache_
.use_premultiplied_alpha
!= quad
->premultiplied_alpha
||
1599 draw_cache_
.needs_blending
!= quad
->ShouldDrawWithBlending() ||
1600 draw_cache_
.matrix_data
.size() >= 8) {
1601 FlushTextureQuadCache();
1602 draw_cache_
.program_id
= binding
.program_id
;
1603 draw_cache_
.resource_id
= resource_id
;
1604 draw_cache_
.use_premultiplied_alpha
= quad
->premultiplied_alpha
;
1605 draw_cache_
.needs_blending
= quad
->ShouldDrawWithBlending();
1607 draw_cache_
.uv_xform_location
= binding
.tex_transform_location
;
1608 draw_cache_
.vertex_opacity_location
= binding
.vertex_opacity_location
;
1609 draw_cache_
.matrix_location
= binding
.matrix_location
;
1610 draw_cache_
.sampler_location
= binding
.sampler_location
;
1613 // Generate the uv-transform
1614 gfx::PointF uv0
= quad
->uv_top_left
;
1615 gfx::PointF uv1
= quad
->uv_bottom_right
;
1616 Float4 uv
= { { uv0
.x(), uv0
.y(), uv1
.x() - uv0
.x(), uv1
.y() - uv0
.y() } };
1617 draw_cache_
.uv_xform_data
.push_back(uv
);
1619 // Generate the vertex opacity
1620 const float opacity
= quad
->opacity();
1621 draw_cache_
.vertex_opacity_data
.push_back(quad
->vertex_opacity
[0] * opacity
);
1622 draw_cache_
.vertex_opacity_data
.push_back(quad
->vertex_opacity
[1] * opacity
);
1623 draw_cache_
.vertex_opacity_data
.push_back(quad
->vertex_opacity
[2] * opacity
);
1624 draw_cache_
.vertex_opacity_data
.push_back(quad
->vertex_opacity
[3] * opacity
);
1626 // Generate the transform matrix
1627 gfx::Transform quad_rect_matrix
;
1628 QuadRectTransform(&quad_rect_matrix
, quad
->quadTransform(), quad
->rect
);
1629 quad_rect_matrix
= frame
->projection_matrix
* quad_rect_matrix
;
1632 quad_rect_matrix
.matrix().asColMajorf(m
.data
);
1633 draw_cache_
.matrix_data
.push_back(m
);
1636 void GLRenderer::DrawTextureQuad(const DrawingFrame
* frame
,
1637 const TextureDrawQuad
* quad
) {
1638 TexCoordPrecision texCoordPrecision
= TexCoordPrecisionRequired(
1639 context_
, highp_threshold_min_
,
1640 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1642 TexTransformTextureProgramBinding binding
;
1644 binding
.Set(GetTextureProgramFlip(texCoordPrecision
), Context());
1646 binding
.Set(GetTextureProgram(texCoordPrecision
), Context());
1647 SetUseProgram(binding
.program_id
);
1648 GLC(Context(), Context()->uniform1i(binding
.sampler_location
, 0));
1649 gfx::PointF uv0
= quad
->uv_top_left
;
1650 gfx::PointF uv1
= quad
->uv_bottom_right
;
1652 Context()->uniform4f(binding
.tex_transform_location
,
1656 uv1
.y() - uv0
.y()));
1659 Context()->uniform1fv(
1660 binding
.vertex_opacity_location
, 4, quad
->vertex_opacity
));
1662 ResourceProvider::ScopedSamplerGL
quad_resource_lock(
1663 resource_provider_
, quad
->resource_id
, GL_TEXTURE_2D
, GL_LINEAR
);
1665 if (!quad
->premultiplied_alpha
) {
1666 // As it turns out, the premultiplied alpha blending function (ONE,
1667 // ONE_MINUS_SRC_ALPHA) will never cause the alpha channel to be set to
1668 // anything less than 1.0f if it is initialized to that value! Therefore,
1669 // premultiplied_alpha being false is the first situation we can generally
1670 // see an alpha channel less than 1.0f coming out of the compositor. This is
1671 // causing platform differences in some layout tests (see
1672 // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use
1673 // a separate blend function for the alpha channel to avoid modifying it.
1674 // Don't use colorMask() for this as it has performance implications on some
1677 Context()->blendFuncSeparate(
1678 GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
, GL_ZERO
, GL_ONE
));
1682 frame
, quad
->quadTransform(), quad
->rect
, binding
.matrix_location
);
1684 if (!quad
->premultiplied_alpha
)
1685 GLC(context_
, context_
->blendFunc(GL_ONE
, GL_ONE_MINUS_SRC_ALPHA
));
1688 void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame
* frame
,
1689 const IOSurfaceDrawQuad
* quad
) {
1690 SetBlendEnabled(quad
->ShouldDrawWithBlending());
1692 TexCoordPrecision texCoordPrecision
= TexCoordPrecisionRequired(
1693 context_
, highp_threshold_min_
,
1694 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1696 TexTransformTextureProgramBinding binding
;
1697 binding
.Set(GetTextureIOSurfaceProgram(texCoordPrecision
), Context());
1699 SetUseProgram(binding
.program_id
);
1700 GLC(Context(), Context()->uniform1i(binding
.sampler_location
, 0));
1701 if (quad
->orientation
== IOSurfaceDrawQuad::FLIPPED
) {
1703 Context()->uniform4f(binding
.tex_transform_location
,
1705 quad
->io_surface_size
.height(),
1706 quad
->io_surface_size
.width(),
1707 quad
->io_surface_size
.height() * -1.0f
));
1710 Context()->uniform4f(binding
.tex_transform_location
,
1713 quad
->io_surface_size
.width(),
1714 quad
->io_surface_size
.height()));
1717 const float vertex_opacity
[] = { quad
->opacity(), quad
->opacity(),
1718 quad
->opacity(), quad
->opacity() };
1720 Context()->uniform1fv(
1721 binding
.vertex_opacity_location
, 4, vertex_opacity
));
1723 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
,
1724 quad
->io_surface_resource_id
);
1726 Context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB
,
1727 lock
.texture_id()));
1730 frame
, quad
->quadTransform(), quad
->rect
, binding
.matrix_location
);
1732 GLC(Context(), Context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0));
1735 void GLRenderer::FinishDrawingFrame(DrawingFrame
* frame
) {
1736 current_framebuffer_lock_
.reset();
1737 swap_buffer_rect_
.Union(gfx::ToEnclosingRect(frame
->root_damage_rect
));
1739 GLC(context_
, context_
->disable(GL_BLEND
));
1740 blend_shadow_
= false;
1742 if (Settings().compositor_frame_message
) {
1743 CompositorFrame compositor_frame
;
1744 compositor_frame
.metadata
= client_
->MakeCompositorFrameMetadata();
1745 output_surface_
->SendFrameToParentCompositor(&compositor_frame
);
1749 void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(); }
1751 bool GLRenderer::FlippedFramebuffer() const { return true; }
1753 void GLRenderer::EnsureScissorTestEnabled() {
1754 if (is_scissor_enabled_
)
1757 FlushTextureQuadCache();
1758 GLC(context_
, context_
->enable(GL_SCISSOR_TEST
));
1759 is_scissor_enabled_
= true;
1762 void GLRenderer::EnsureScissorTestDisabled() {
1763 if (!is_scissor_enabled_
)
1766 FlushTextureQuadCache();
1767 GLC(context_
, context_
->disable(GL_SCISSOR_TEST
));
1768 is_scissor_enabled_
= false;
1771 void GLRenderer::ToGLMatrix(float* gl_matrix
, const gfx::Transform
& transform
) {
1772 transform
.matrix().asColMajorf(gl_matrix
);
1775 void GLRenderer::SetShaderQuadF(const gfx::QuadF
& quad
, int quad_location
) {
1776 if (quad_location
== -1)
1780 point
[0] = quad
.p1().x();
1781 point
[1] = quad
.p1().y();
1782 point
[2] = quad
.p2().x();
1783 point
[3] = quad
.p2().y();
1784 point
[4] = quad
.p3().x();
1785 point
[5] = quad
.p3().y();
1786 point
[6] = quad
.p4().x();
1787 point
[7] = quad
.p4().y();
1788 GLC(context_
, context_
->uniform2fv(quad_location
, 4, point
));
1791 void GLRenderer::SetShaderOpacity(float opacity
, int alpha_location
) {
1792 if (alpha_location
!= -1)
1793 GLC(context_
, context_
->uniform1f(alpha_location
, opacity
));
1796 void GLRenderer::SetBlendEnabled(bool enabled
) {
1797 if (enabled
== blend_shadow_
)
1801 GLC(context_
, context_
->enable(GL_BLEND
));
1803 GLC(context_
, context_
->disable(GL_BLEND
));
1804 blend_shadow_
= enabled
;
1807 void GLRenderer::SetUseProgram(unsigned program
) {
1808 if (program
== program_shadow_
)
1810 GLC(context_
, context_
->useProgram(program
));
1811 program_shadow_
= program
;
1814 void GLRenderer::DrawQuadGeometry(const DrawingFrame
* frame
,
1815 const gfx::Transform
& draw_transform
,
1816 const gfx::RectF
& quad_rect
,
1817 int matrix_location
) {
1818 gfx::Transform quad_rect_matrix
;
1819 QuadRectTransform(&quad_rect_matrix
, draw_transform
, quad_rect
);
1820 static float gl_matrix
[16];
1821 ToGLMatrix(&gl_matrix
[0], frame
->projection_matrix
* quad_rect_matrix
);
1823 context_
->uniformMatrix4fv(matrix_location
, 1, false, &gl_matrix
[0]));
1825 GLC(context_
, context_
->drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0));
1828 void GLRenderer::CopyTextureToFramebuffer(const DrawingFrame
* frame
,
1831 const gfx::Transform
& draw_matrix
) {
1832 TexCoordPrecision texCoordPrecision
= TexCoordPrecisionRequired(
1833 context_
, highp_threshold_min_
, rect
.bottom_right());
1834 const RenderPassProgram
* program
= GetRenderPassProgram(texCoordPrecision
);
1836 GLC(Context(), Context()->bindTexture(GL_TEXTURE_2D
, texture_id
));
1838 SetUseProgram(program
->program());
1840 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
1842 Context()->uniform4f(program
->vertex_shader().tex_transform_location(),
1847 SetShaderOpacity(1, program
->fragment_shader().alpha_location());
1849 frame
, draw_matrix
, rect
, program
->vertex_shader().matrix_location());
1852 void GLRenderer::Finish() {
1853 TRACE_EVENT0("cc", "GLRenderer::finish");
1857 bool GLRenderer::SwapBuffers() {
1859 DCHECK(!is_backbuffer_discarded_
);
1861 TRACE_EVENT0("cc", "GLRenderer::SwapBuffers");
1862 // We're done! Time to swapbuffers!
1864 if (capabilities_
.using_partial_swap
&& client_
->AllowPartialSwap()) {
1865 // If supported, we can save significant bandwidth by only swapping the
1866 // damaged/scissored region (clamped to the viewport)
1867 swap_buffer_rect_
.Intersect(gfx::Rect(ViewportSize()));
1868 int flipped_y_pos_of_rect_bottom
=
1869 ViewportHeight() - swap_buffer_rect_
.y() - swap_buffer_rect_
.height();
1870 output_surface_
->PostSubBuffer(gfx::Rect(swap_buffer_rect_
.x(),
1871 flipped_y_pos_of_rect_bottom
,
1872 swap_buffer_rect_
.width(),
1873 swap_buffer_rect_
.height()),
1876 output_surface_
->SwapBuffers(LatencyInfo());
1879 swap_buffer_rect_
= gfx::Rect();
1881 // We don't have real fences, so we mark read fences as passed
1882 // assuming a double-buffered GPU pipeline. A texture can be
1883 // written to after one full frame has past since it was last read.
1884 if (last_swap_fence_
)
1885 static_cast<SimpleSwapFence
*>(last_swap_fence_
.get())->SetHasPassed();
1886 last_swap_fence_
= resource_provider_
->GetReadLockFence();
1887 resource_provider_
->SetReadLockFence(new SimpleSwapFence());
1892 void GLRenderer::ReceiveCompositorFrameAck(const CompositorFrameAck
& ack
) {
1893 onSwapBuffersComplete();
1896 void GLRenderer::onSwapBuffersComplete() { client_
->OnSwapBuffersComplete(); }
1898 void GLRenderer::onMemoryAllocationChanged(
1899 WebGraphicsMemoryAllocation allocation
) {
1900 // Just ignore the memory manager when it says to set the limit to zero
1901 // bytes. This will happen when the memory manager thinks that the renderer
1902 // is not visible (which the renderer knows better).
1903 if (allocation
.bytesLimitWhenVisible
) {
1904 ManagedMemoryPolicy
policy(
1905 allocation
.bytesLimitWhenVisible
,
1906 PriorityCutoff(allocation
.priorityCutoffWhenVisible
),
1907 allocation
.bytesLimitWhenNotVisible
,
1908 PriorityCutoff(allocation
.priorityCutoffWhenNotVisible
));
1910 if (allocation
.enforceButDoNotKeepAsPolicy
)
1911 client_
->EnforceManagedMemoryPolicy(policy
);
1913 client_
->SetManagedMemoryPolicy(policy
);
1916 bool old_discard_backbuffer_when_not_visible
=
1917 discard_backbuffer_when_not_visible_
;
1918 discard_backbuffer_when_not_visible_
= !allocation
.suggestHaveBackbuffer
;
1919 EnforceMemoryPolicy();
1920 if (allocation
.enforceButDoNotKeepAsPolicy
)
1921 discard_backbuffer_when_not_visible_
=
1922 old_discard_backbuffer_when_not_visible
;
1925 ManagedMemoryPolicy::PriorityCutoff
GLRenderer::PriorityCutoff(
1926 WebKit::WebGraphicsMemoryAllocation::PriorityCutoff priority_cutoff
) {
1927 // This is simple a 1:1 map, the names differ only because the WebKit names
1928 // should be to match the cc names.
1929 switch (priority_cutoff
) {
1930 case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowNothing
:
1931 return ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING
;
1932 case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleOnly
:
1933 return ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY
;
1934 case WebKit::WebGraphicsMemoryAllocation::
1935 PriorityCutoffAllowVisibleAndNearby
:
1936 return ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE
;
1937 case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowEverything
:
1938 return ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING
;
1941 return ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING
;
1944 void GLRenderer::EnforceMemoryPolicy() {
1946 TRACE_EVENT0("cc", "GLRenderer::EnforceMemoryPolicy dropping resources");
1947 ReleaseRenderPassTextures();
1948 if (discard_backbuffer_when_not_visible_
)
1949 DiscardBackbuffer();
1950 resource_provider_
->ReleaseCachedData();
1951 GLC(context_
, context_
->flush());
1955 void GLRenderer::DiscardBackbuffer() {
1956 if (is_backbuffer_discarded_
)
1959 output_surface_
->DiscardBackbuffer();
1961 is_backbuffer_discarded_
= true;
1963 // Damage tracker needs a full reset every time framebuffer is discarded.
1964 client_
->SetFullRootLayerDamage();
1967 void GLRenderer::EnsureBackbuffer() {
1968 if (!is_backbuffer_discarded_
)
1971 output_surface_
->EnsureBackbuffer();
1972 is_backbuffer_discarded_
= false;
1975 void GLRenderer::onContextLost() { client_
->DidLoseOutputSurface(); }
1977 void GLRenderer::GetFramebufferPixels(void* pixels
, gfx::Rect rect
) {
1978 DCHECK(rect
.right() <= ViewportWidth());
1979 DCHECK(rect
.bottom() <= ViewportHeight());
1984 MakeContextCurrent();
1986 bool do_workaround
= NeedsIOSurfaceReadbackWorkaround();
1988 GLuint temporary_texture
= 0;
1989 GLuint temporary_fbo
= 0;
1991 if (do_workaround
) {
1992 // On Mac OS X, calling glReadPixels() against an FBO whose color attachment
1993 // is an IOSurface-backed texture causes corruption of future glReadPixels()
1994 // calls, even those on different OpenGL contexts. It is believed that this
1995 // is the root cause of top crasher
1996 // http://crbug.com/99393. <rdar://problem/10949687>
1998 temporary_texture
= context_
->createTexture();
1999 GLC(context_
, context_
->bindTexture(GL_TEXTURE_2D
, temporary_texture
));
2001 context_
->texParameteri(
2002 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2004 context_
->texParameteri(
2005 GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2007 context_
->texParameteri(
2008 GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2010 context_
->texParameteri(
2011 GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2012 // Copy the contents of the current (IOSurface-backed) framebuffer into a
2013 // temporary texture.
2015 context_
->copyTexImage2D(GL_TEXTURE_2D
,
2020 ViewportSize().width(),
2021 ViewportSize().height(),
2023 temporary_fbo
= context_
->createFramebuffer();
2024 // Attach this texture to an FBO, and perform the readback from that FBO.
2025 GLC(context_
, context_
->bindFramebuffer(GL_FRAMEBUFFER
, temporary_fbo
));
2027 context_
->framebufferTexture2D(GL_FRAMEBUFFER
,
2028 GL_COLOR_ATTACHMENT0
,
2033 DCHECK(context_
->checkFramebufferStatus(GL_FRAMEBUFFER
) ==
2034 GL_FRAMEBUFFER_COMPLETE
);
2037 scoped_ptr
<uint8_t[]> src_pixels(
2038 new uint8_t[rect
.width() * rect
.height() * 4]);
2040 context_
->readPixels(rect
.x(),
2041 ViewportSize().height() - rect
.bottom(),
2048 uint8_t* dest_pixels
= static_cast<uint8_t*>(pixels
);
2049 size_t row_bytes
= rect
.width() * 4;
2050 int num_rows
= rect
.height();
2051 size_t total_bytes
= num_rows
* row_bytes
;
2052 for (size_t dest_y
= 0; dest_y
< total_bytes
; dest_y
+= row_bytes
) {
2054 size_t src_y
= total_bytes
- dest_y
- row_bytes
;
2055 // Swizzle BGRA -> RGBA.
2056 for (size_t x
= 0; x
< row_bytes
; x
+= 4) {
2057 dest_pixels
[dest_y
+ (x
+ 0)] = src_pixels
.get()[src_y
+ (x
+ 2)];
2058 dest_pixels
[dest_y
+ (x
+ 1)] = src_pixels
.get()[src_y
+ (x
+ 1)];
2059 dest_pixels
[dest_y
+ (x
+ 2)] = src_pixels
.get()[src_y
+ (x
+ 0)];
2060 dest_pixels
[dest_y
+ (x
+ 3)] = src_pixels
.get()[src_y
+ (x
+ 3)];
2064 if (do_workaround
) {
2066 GLC(context_
, context_
->bindFramebuffer(GL_FRAMEBUFFER
, 0));
2067 GLC(context_
, context_
->bindTexture(GL_TEXTURE_2D
, 0));
2068 GLC(context_
, context_
->deleteFramebuffer(temporary_fbo
));
2069 GLC(context_
, context_
->deleteTexture(temporary_texture
));
2072 EnforceMemoryPolicy();
2075 bool GLRenderer::GetFramebufferTexture(ScopedResource
* texture
,
2076 gfx::Rect device_rect
) {
2077 DCHECK(!texture
->id() || (texture
->size() == device_rect
.size() &&
2078 texture
->format() == GL_RGB
));
2080 if (!texture
->id() && !texture
->Allocate(device_rect
.size(),
2082 ResourceProvider::TextureUsageAny
))
2085 ResourceProvider::ScopedWriteLockGL
lock(resource_provider_
, texture
->id());
2086 GLC(context_
, context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id()));
2088 context_
->copyTexImage2D(GL_TEXTURE_2D
,
2093 device_rect
.width(),
2094 device_rect
.height(),
2099 bool GLRenderer::UseScopedTexture(DrawingFrame
* frame
,
2100 const ScopedResource
* texture
,
2101 gfx::Rect viewport_rect
) {
2102 DCHECK(texture
->id());
2103 frame
->current_render_pass
= NULL
;
2104 frame
->current_texture
= texture
;
2106 return BindFramebufferToTexture(frame
, texture
, viewport_rect
);
2109 void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame
* frame
) {
2110 current_framebuffer_lock_
.reset();
2111 output_surface_
->BindFramebuffer();
2114 bool GLRenderer::BindFramebufferToTexture(DrawingFrame
* frame
,
2115 const ScopedResource
* texture
,
2116 gfx::Rect framebuffer_rect
) {
2117 DCHECK(texture
->id());
2120 context_
->bindFramebuffer(GL_FRAMEBUFFER
, offscreen_framebuffer_id_
));
2121 current_framebuffer_lock_
=
2122 make_scoped_ptr(new ResourceProvider::ScopedWriteLockGL(
2123 resource_provider_
, texture
->id()));
2124 unsigned texture_id
= current_framebuffer_lock_
->texture_id();
2126 context_
->framebufferTexture2D(
2127 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, GL_TEXTURE_2D
, texture_id
, 0));
2129 DCHECK(context_
->checkFramebufferStatus(GL_FRAMEBUFFER
) ==
2130 GL_FRAMEBUFFER_COMPLETE
|| IsContextLost());
2132 InitializeMatrices(frame
, framebuffer_rect
, false);
2133 SetDrawViewportSize(framebuffer_rect
.size());
2138 void GLRenderer::SetScissorTestRect(gfx::Rect scissor_rect
) {
2139 EnsureScissorTestEnabled();
2141 // Don't unnecessarily ask the context to change the scissor, because it
2142 // may cause undesired GPU pipeline flushes.
2143 if (scissor_rect
== scissor_rect_
)
2146 scissor_rect_
= scissor_rect
;
2147 FlushTextureQuadCache();
2149 context_
->scissor(scissor_rect
.x(),
2151 scissor_rect
.width(),
2152 scissor_rect
.height()));
2155 void GLRenderer::SetDrawViewportSize(gfx::Size viewport_size
) {
2157 context_
->viewport(0, 0, viewport_size
.width(), viewport_size
.height()));
2160 bool GLRenderer::MakeContextCurrent() { return context_
->makeContextCurrent(); }
2162 bool GLRenderer::InitializeSharedObjects() {
2163 TRACE_EVENT0("cc", "GLRenderer::InitializeSharedObjects");
2164 MakeContextCurrent();
2166 // Create an FBO for doing offscreen rendering.
2167 GLC(context_
, offscreen_framebuffer_id_
= context_
->createFramebuffer());
2169 // We will always need these programs to render, so create the programs
2170 // eagerly so that the shader compilation can start while we do other work.
2171 // Other programs are created lazily on first access.
2172 shared_geometry_
= make_scoped_ptr(
2173 new GeometryBinding(context_
, QuadVertexRect()));
2174 render_pass_program_
= make_scoped_ptr(
2175 new RenderPassProgram(context_
, TexCoordPrecisionMedium
));
2176 render_pass_program_highp_
= make_scoped_ptr(
2177 new RenderPassProgram(context_
, TexCoordPrecisionHigh
));
2178 tile_program_
= make_scoped_ptr(
2179 new TileProgram(context_
, TexCoordPrecisionMedium
));
2180 tile_program_opaque_
= make_scoped_ptr(
2181 new TileProgramOpaque(context_
, TexCoordPrecisionMedium
));
2183 GLC(context_
, context_
->flush());
2188 const GLRenderer::TileCheckerboardProgram
*
2189 GLRenderer::GetTileCheckerboardProgram() {
2190 if (!tile_checkerboard_program_
)
2191 tile_checkerboard_program_
= make_scoped_ptr(
2192 new TileCheckerboardProgram(context_
, TexCoordPrecisionNA
));
2193 if (!tile_checkerboard_program_
->initialized()) {
2194 TRACE_EVENT0("cc", "GLRenderer::checkerboardProgram::initalize");
2195 tile_checkerboard_program_
->Initialize(context_
, is_using_bind_uniform_
);
2197 return tile_checkerboard_program_
.get();
2200 const GLRenderer::DebugBorderProgram
* GLRenderer::GetDebugBorderProgram() {
2201 if (!debug_border_program_
)
2202 debug_border_program_
= make_scoped_ptr(
2203 new DebugBorderProgram(context_
, TexCoordPrecisionNA
));
2204 if (!debug_border_program_
->initialized()) {
2205 TRACE_EVENT0("cc", "GLRenderer::debugBorderProgram::initialize");
2206 debug_border_program_
->Initialize(context_
, is_using_bind_uniform_
);
2208 return debug_border_program_
.get();
2211 const GLRenderer::SolidColorProgram
* GLRenderer::GetSolidColorProgram() {
2212 if (!solid_color_program_
)
2213 solid_color_program_
= make_scoped_ptr(
2214 new SolidColorProgram(context_
, TexCoordPrecisionNA
));
2215 if (!solid_color_program_
->initialized()) {
2216 TRACE_EVENT0("cc", "GLRenderer::solidColorProgram::initialize");
2217 solid_color_program_
->Initialize(context_
, is_using_bind_uniform_
);
2219 return solid_color_program_
.get();
2222 const GLRenderer::SolidColorProgramAA
* GLRenderer::GetSolidColorProgramAA() {
2223 if (!solid_color_program_aa_
) {
2224 solid_color_program_aa_
=
2225 make_scoped_ptr(new SolidColorProgramAA(context_
, TexCoordPrecisionNA
));
2227 if (!solid_color_program_aa_
->initialized()) {
2228 TRACE_EVENT0("cc", "GLRenderer::solidColorProgramAA::initialize");
2229 solid_color_program_aa_
->Initialize(context_
, is_using_bind_uniform_
);
2231 return solid_color_program_aa_
.get();
2234 const GLRenderer::RenderPassProgram
* GLRenderer::GetRenderPassProgram(
2235 TexCoordPrecision precision
) {
2236 scoped_ptr
<RenderPassProgram
> &program
=
2237 (precision
== TexCoordPrecisionHigh
) ? render_pass_program_highp_
2238 : render_pass_program_
;
2240 if (!program
->initialized()) {
2241 TRACE_EVENT0("cc", "GLRenderer::renderPassProgram::initialize");
2242 program
->Initialize(context_
, is_using_bind_uniform_
);
2244 return program
.get();
2247 const GLRenderer::RenderPassProgramAA
* GLRenderer::GetRenderPassProgramAA(
2248 TexCoordPrecision precision
) {
2249 scoped_ptr
<RenderPassProgramAA
> &program
=
2250 (precision
== TexCoordPrecisionHigh
) ? render_pass_program_aa_highp_
2251 : render_pass_program_aa_
;
2254 make_scoped_ptr(new RenderPassProgramAA(context_
, precision
));
2255 if (!program
->initialized()) {
2256 TRACE_EVENT0("cc", "GLRenderer::renderPassProgramAA::initialize");
2257 program
->Initialize(context_
, is_using_bind_uniform_
);
2259 return program
.get();
2262 const GLRenderer::RenderPassMaskProgram
*
2263 GLRenderer::GetRenderPassMaskProgram(TexCoordPrecision precision
) {
2264 scoped_ptr
<RenderPassMaskProgram
> &program
=
2265 (precision
== TexCoordPrecisionHigh
) ? render_pass_mask_program_highp_
2266 : render_pass_mask_program_
;
2268 program
= make_scoped_ptr(new RenderPassMaskProgram(context_
, precision
));
2269 if (!program
->initialized()) {
2270 TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize");
2271 program
->Initialize(context_
, is_using_bind_uniform_
);
2273 return program
.get();
2276 const GLRenderer::RenderPassMaskProgramAA
*
2277 GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision
) {
2278 scoped_ptr
<RenderPassMaskProgramAA
> &program
=
2279 (precision
== TexCoordPrecisionHigh
) ? render_pass_mask_program_aa_highp_
2280 : render_pass_mask_program_aa_
;
2283 make_scoped_ptr(new RenderPassMaskProgramAA(context_
, precision
));
2284 if (!program
->initialized()) {
2285 TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize");
2286 program
->Initialize(context_
, is_using_bind_uniform_
);
2288 return program
.get();
2291 const GLRenderer::RenderPassColorMatrixProgram
*
2292 GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision
) {
2293 scoped_ptr
<RenderPassColorMatrixProgram
> &program
=
2294 (precision
== TexCoordPrecisionHigh
) ?
2295 render_pass_color_matrix_program_highp_
:
2296 render_pass_color_matrix_program_
;
2298 program
= make_scoped_ptr(
2299 new RenderPassColorMatrixProgram(context_
, precision
));
2300 if (!program
->initialized()) {
2301 TRACE_EVENT0("cc", "GLRenderer::renderPassColorMatrixProgram::initialize");
2302 program
->Initialize(context_
, is_using_bind_uniform_
);
2304 return program
.get();
2307 const GLRenderer::RenderPassColorMatrixProgramAA
*
2308 GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision
) {
2309 scoped_ptr
<RenderPassColorMatrixProgramAA
> &program
=
2310 (precision
== TexCoordPrecisionHigh
) ?
2311 render_pass_color_matrix_program_aa_highp_
:
2312 render_pass_color_matrix_program_aa_
;
2314 program
= make_scoped_ptr(
2315 new RenderPassColorMatrixProgramAA(context_
, precision
));
2316 if (!program
->initialized()) {
2318 "GLRenderer::renderPassColorMatrixProgramAA::initialize");
2319 program
->Initialize(context_
, is_using_bind_uniform_
);
2321 return program
.get();
2324 const GLRenderer::RenderPassMaskColorMatrixProgram
*
2325 GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision
) {
2326 scoped_ptr
<RenderPassMaskColorMatrixProgram
> &program
=
2327 (precision
== TexCoordPrecisionHigh
) ?
2328 render_pass_mask_color_matrix_program_highp_
:
2329 render_pass_mask_color_matrix_program_
;
2331 program
= make_scoped_ptr(
2332 new RenderPassMaskColorMatrixProgram(context_
, precision
));
2333 if (!program
->initialized()) {
2335 "GLRenderer::renderPassMaskColorMatrixProgram::initialize");
2336 program
->Initialize(context_
, is_using_bind_uniform_
);
2338 return program
.get();
2341 const GLRenderer::RenderPassMaskColorMatrixProgramAA
*
2342 GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision
) {
2343 scoped_ptr
<RenderPassMaskColorMatrixProgramAA
> &program
=
2344 (precision
== TexCoordPrecisionHigh
) ?
2345 render_pass_mask_color_matrix_program_aa_highp_
:
2346 render_pass_mask_color_matrix_program_aa_
;
2348 program
= make_scoped_ptr(
2349 new RenderPassMaskColorMatrixProgramAA(context_
, precision
));
2350 if (!program
->initialized()) {
2352 "GLRenderer::renderPassMaskColorMatrixProgramAA::initialize");
2353 program
->Initialize(context_
, is_using_bind_uniform_
);
2355 return program
.get();
2358 const GLRenderer::TileProgram
* GLRenderer::GetTileProgram() {
2359 DCHECK(tile_program_
);
2360 if (!tile_program_
->initialized()) {
2361 TRACE_EVENT0("cc", "GLRenderer::tileProgram::initialize");
2362 tile_program_
->Initialize(context_
, is_using_bind_uniform_
);
2364 return tile_program_
.get();
2367 const GLRenderer::TileProgramOpaque
* GLRenderer::GetTileProgramOpaque() {
2368 DCHECK(tile_program_opaque_
);
2369 if (!tile_program_opaque_
->initialized()) {
2370 TRACE_EVENT0("cc", "GLRenderer::tileProgramOpaque::initialize");
2371 tile_program_opaque_
->Initialize(context_
, is_using_bind_uniform_
);
2373 return tile_program_opaque_
.get();
2376 const GLRenderer::TileProgramAA
* GLRenderer::GetTileProgramAA() {
2377 if (!tile_program_aa_
)
2378 tile_program_aa_
= make_scoped_ptr(
2379 new TileProgramAA(context_
, TexCoordPrecisionMedium
));
2380 if (!tile_program_aa_
->initialized()) {
2381 TRACE_EVENT0("cc", "GLRenderer::tileProgramAA::initialize");
2382 tile_program_aa_
->Initialize(context_
, is_using_bind_uniform_
);
2384 return tile_program_aa_
.get();
2387 const GLRenderer::TileProgramSwizzle
* GLRenderer::GetTileProgramSwizzle() {
2388 if (!tile_program_swizzle_
)
2389 tile_program_swizzle_
= make_scoped_ptr(
2390 new TileProgramSwizzle(context_
, TexCoordPrecisionMedium
));
2391 if (!tile_program_swizzle_
->initialized()) {
2392 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzle::initialize");
2393 tile_program_swizzle_
->Initialize(context_
, is_using_bind_uniform_
);
2395 return tile_program_swizzle_
.get();
2398 const GLRenderer::TileProgramSwizzleOpaque
*
2399 GLRenderer::GetTileProgramSwizzleOpaque() {
2400 if (!tile_program_swizzle_opaque_
)
2401 tile_program_swizzle_opaque_
= make_scoped_ptr(
2402 new TileProgramSwizzleOpaque(context_
, TexCoordPrecisionMedium
));
2403 if (!tile_program_swizzle_opaque_
->initialized()) {
2404 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleOpaque::initialize");
2405 tile_program_swizzle_opaque_
->Initialize(context_
, is_using_bind_uniform_
);
2407 return tile_program_swizzle_opaque_
.get();
2410 const GLRenderer::TileProgramSwizzleAA
* GLRenderer::GetTileProgramSwizzleAA() {
2411 if (!tile_program_swizzle_aa_
)
2412 tile_program_swizzle_aa_
= make_scoped_ptr(
2413 new TileProgramSwizzleAA(context_
, TexCoordPrecisionMedium
));
2414 if (!tile_program_swizzle_aa_
->initialized()) {
2415 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleAA::initialize");
2416 tile_program_swizzle_aa_
->Initialize(context_
, is_using_bind_uniform_
);
2418 return tile_program_swizzle_aa_
.get();
2421 const GLRenderer::TextureProgram
* GLRenderer::GetTextureProgram(
2422 TexCoordPrecision precision
) {
2423 scoped_ptr
<TextureProgram
> &program
=
2424 (precision
== TexCoordPrecisionHigh
) ? texture_program_highp_
2427 program
= make_scoped_ptr(new TextureProgram(context_
, precision
));
2428 if (!program
->initialized()) {
2429 TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize");
2430 program
->Initialize(context_
, is_using_bind_uniform_
);
2432 return program
.get();
2435 const GLRenderer::TextureProgramFlip
* GLRenderer::GetTextureProgramFlip(
2436 TexCoordPrecision precision
) {
2437 scoped_ptr
<TextureProgramFlip
> &program
=
2438 (precision
== TexCoordPrecisionHigh
) ? texture_program_flip_highp_
2439 : texture_program_flip_
;
2441 program
= make_scoped_ptr(new TextureProgramFlip(context_
, precision
));
2442 if (!program
->initialized()) {
2443 TRACE_EVENT0("cc", "GLRenderer::textureProgramFlip::initialize");
2444 program
->Initialize(context_
, is_using_bind_uniform_
);
2446 return program
.get();
2449 const GLRenderer::TextureIOSurfaceProgram
*
2450 GLRenderer::GetTextureIOSurfaceProgram(TexCoordPrecision precision
) {
2451 scoped_ptr
<TextureIOSurfaceProgram
> &program
=
2452 (precision
== TexCoordPrecisionHigh
) ? texture_io_surface_program_highp_
2453 : texture_io_surface_program_
;
2456 make_scoped_ptr(new TextureIOSurfaceProgram(context_
, precision
));
2457 if (!program
->initialized()) {
2458 TRACE_EVENT0("cc", "GLRenderer::textureIOSurfaceProgram::initialize");
2459 program
->Initialize(context_
, is_using_bind_uniform_
);
2461 return program
.get();
2464 const GLRenderer::VideoYUVProgram
* GLRenderer::GetVideoYUVProgram(
2465 TexCoordPrecision precision
) {
2466 scoped_ptr
<VideoYUVProgram
> &program
=
2467 (precision
== TexCoordPrecisionHigh
) ? video_yuv_program_highp_
2468 : video_yuv_program_
;
2470 program
= make_scoped_ptr(new VideoYUVProgram(context_
, precision
));
2471 if (!program
->initialized()) {
2472 TRACE_EVENT0("cc", "GLRenderer::videoYUVProgram::initialize");
2473 program
->Initialize(context_
, is_using_bind_uniform_
);
2475 return program
.get();
2478 const GLRenderer::VideoStreamTextureProgram
*
2479 GLRenderer::GetVideoStreamTextureProgram(TexCoordPrecision precision
) {
2480 if (!Capabilities().using_egl_image
)
2482 scoped_ptr
<VideoStreamTextureProgram
> &program
=
2483 (precision
== TexCoordPrecisionHigh
) ? video_stream_texture_program_highp_
2484 : video_stream_texture_program_
;
2487 make_scoped_ptr(new VideoStreamTextureProgram(context_
, precision
));
2488 if (!program
->initialized()) {
2489 TRACE_EVENT0("cc", "GLRenderer::streamTextureProgram::initialize");
2490 program
->Initialize(context_
, is_using_bind_uniform_
);
2492 return program
.get();
2495 void GLRenderer::CleanupSharedObjects() {
2496 MakeContextCurrent();
2498 shared_geometry_
.reset();
2501 tile_program_
->Cleanup(context_
);
2502 if (tile_program_opaque_
)
2503 tile_program_opaque_
->Cleanup(context_
);
2504 if (tile_program_swizzle_
)
2505 tile_program_swizzle_
->Cleanup(context_
);
2506 if (tile_program_swizzle_opaque_
)
2507 tile_program_swizzle_opaque_
->Cleanup(context_
);
2508 if (tile_program_aa_
)
2509 tile_program_aa_
->Cleanup(context_
);
2510 if (tile_program_swizzle_aa_
)
2511 tile_program_swizzle_aa_
->Cleanup(context_
);
2512 if (tile_checkerboard_program_
)
2513 tile_checkerboard_program_
->Cleanup(context_
);
2515 if (render_pass_mask_program_
)
2516 render_pass_mask_program_
->Cleanup(context_
);
2517 if (render_pass_program_
)
2518 render_pass_program_
->Cleanup(context_
);
2519 if (render_pass_mask_program_aa_
)
2520 render_pass_mask_program_aa_
->Cleanup(context_
);
2521 if (render_pass_program_aa_
)
2522 render_pass_program_aa_
->Cleanup(context_
);
2523 if (render_pass_color_matrix_program_
)
2524 render_pass_color_matrix_program_
->Cleanup(context_
);
2525 if (render_pass_mask_color_matrix_program_aa_
)
2526 render_pass_mask_color_matrix_program_aa_
->Cleanup(context_
);
2527 if (render_pass_color_matrix_program_aa_
)
2528 render_pass_color_matrix_program_aa_
->Cleanup(context_
);
2529 if (render_pass_mask_color_matrix_program_
)
2530 render_pass_mask_color_matrix_program_
->Cleanup(context_
);
2532 if (render_pass_mask_program_highp_
)
2533 render_pass_mask_program_highp_
->Cleanup(context_
);
2534 if (render_pass_program_highp_
)
2535 render_pass_program_highp_
->Cleanup(context_
);
2536 if (render_pass_mask_program_aa_highp_
)
2537 render_pass_mask_program_aa_highp_
->Cleanup(context_
);
2538 if (render_pass_program_aa_highp_
)
2539 render_pass_program_aa_highp_
->Cleanup(context_
);
2540 if (render_pass_color_matrix_program_highp_
)
2541 render_pass_color_matrix_program_highp_
->Cleanup(context_
);
2542 if (render_pass_mask_color_matrix_program_aa_highp_
)
2543 render_pass_mask_color_matrix_program_aa_highp_
->Cleanup(context_
);
2544 if (render_pass_color_matrix_program_aa_highp_
)
2545 render_pass_color_matrix_program_aa_highp_
->Cleanup(context_
);
2546 if (render_pass_mask_color_matrix_program_highp_
)
2547 render_pass_mask_color_matrix_program_highp_
->Cleanup(context_
);
2549 if (texture_program_
)
2550 texture_program_
->Cleanup(context_
);
2551 if (texture_program_flip_
)
2552 texture_program_flip_
->Cleanup(context_
);
2553 if (texture_io_surface_program_
)
2554 texture_io_surface_program_
->Cleanup(context_
);
2556 if (texture_program_highp_
)
2557 texture_program_highp_
->Cleanup(context_
);
2558 if (texture_program_flip_highp_
)
2559 texture_program_flip_highp_
->Cleanup(context_
);
2560 if (texture_io_surface_program_highp_
)
2561 texture_io_surface_program_highp_
->Cleanup(context_
);
2563 if (video_yuv_program_
)
2564 video_yuv_program_
->Cleanup(context_
);
2565 if (video_stream_texture_program_
)
2566 video_stream_texture_program_
->Cleanup(context_
);
2568 if (video_yuv_program_highp_
)
2569 video_yuv_program_highp_
->Cleanup(context_
);
2570 if (video_stream_texture_program_highp_
)
2571 video_stream_texture_program_highp_
->Cleanup(context_
);
2573 if (debug_border_program_
)
2574 debug_border_program_
->Cleanup(context_
);
2575 if (solid_color_program_
)
2576 solid_color_program_
->Cleanup(context_
);
2577 if (solid_color_program_aa_
)
2578 solid_color_program_aa_
->Cleanup(context_
);
2580 if (offscreen_framebuffer_id_
)
2581 GLC(context_
, context_
->deleteFramebuffer(offscreen_framebuffer_id_
));
2583 if (on_demand_tile_raster_resource_id_
)
2584 resource_provider_
->DeleteResource(on_demand_tile_raster_resource_id_
);
2586 ReleaseRenderPassTextures();
2589 bool GLRenderer::IsContextLost() {
2590 return (context_
->getGraphicsResetStatusARB() != GL_NO_ERROR
);