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 // Smallest unit that impact anti-aliasing output. We use this to
85 // determine when anti-aliasing is unnecessary.
86 const float kAntiAliasingEpsilon
= 1.0f
/ 1024.0f
;
88 } // anonymous namespace
90 scoped_ptr
<GLRenderer
> GLRenderer::Create(RendererClient
* client
,
91 OutputSurface
* output_surface
,
92 ResourceProvider
* resource_provider
,
93 int highp_threshold_min
) {
94 scoped_ptr
<GLRenderer
> renderer(new GLRenderer(
95 client
, output_surface
, resource_provider
, highp_threshold_min
));
96 if (!renderer
->Initialize())
97 return scoped_ptr
<GLRenderer
>();
99 return renderer
.Pass();
102 GLRenderer::GLRenderer(RendererClient
* client
,
103 OutputSurface
* output_surface
,
104 ResourceProvider
* resource_provider
,
105 int highp_threshold_min
)
106 : DirectRenderer(client
, resource_provider
),
107 offscreen_framebuffer_id_(0),
108 shared_geometry_quad_(gfx::RectF(-0.5f
, -0.5f
, 1.0f
, 1.0f
)),
109 output_surface_(output_surface
),
110 context_(output_surface
->context3d()),
111 is_viewport_changed_(false),
112 is_backbuffer_discarded_(false),
113 discard_backbuffer_when_not_visible_(false),
114 is_using_bind_uniform_(false),
116 is_scissor_enabled_(false),
117 highp_threshold_min_(highp_threshold_min
),
118 on_demand_tile_raster_resource_id_(0) {
122 bool GLRenderer::Initialize() {
123 if (!context_
->makeContextCurrent())
126 context_
->pushGroupMarkerEXT("CompositorContext");
128 std::string extensions_string
=
129 UTF16ToASCII(context_
->getString(GL_EXTENSIONS
));
130 std::vector
<std::string
> extensions_list
;
131 base::SplitString(extensions_string
, ' ', &extensions_list
);
132 std::set
<std::string
> extensions(extensions_list
.begin(),
133 extensions_list
.end());
135 if (Settings().accelerate_painting
&&
136 extensions
.count("GL_EXT_texture_format_BGRA8888") &&
137 extensions
.count("GL_EXT_read_format_bgra"))
138 capabilities_
.using_accelerated_painting
= true;
140 capabilities_
.using_accelerated_painting
= false;
142 capabilities_
.using_partial_swap
=
143 Settings().partial_swap_enabled
&&
144 extensions
.count("GL_CHROMIUM_post_sub_buffer");
146 // Use the SwapBuffers callback only with the threaded proxy.
147 if (client_
->HasImplThread())
148 capabilities_
.using_swap_complete_callback
=
149 extensions
.count("GL_CHROMIUM_swapbuffers_complete_callback") > 0;
151 capabilities_
.using_set_visibility
=
152 extensions
.count("GL_CHROMIUM_set_visibility") > 0;
154 if (extensions
.count("GL_CHROMIUM_iosurface") > 0)
155 DCHECK_GT(extensions
.count("GL_ARB_texture_rectangle"), 0u);
157 capabilities_
.using_gpu_memory_manager
=
158 extensions
.count("GL_CHROMIUM_gpu_memory_manager") > 0 &&
159 Settings().use_memory_management
;
160 if (capabilities_
.using_gpu_memory_manager
)
161 context_
->setMemoryAllocationChangedCallbackCHROMIUM(this);
163 capabilities_
.using_egl_image
=
164 extensions
.count("GL_OES_EGL_image_external") > 0;
166 capabilities_
.max_texture_size
= resource_provider_
->max_texture_size();
167 capabilities_
.best_texture_format
= resource_provider_
->best_texture_format();
169 // The updater can access textures while the GLRenderer is using them.
170 capabilities_
.allow_partial_texture_updates
= true;
172 // Check for texture fast paths. Currently we always use MO8 textures,
173 // so we only need to avoid POT textures if we have an NPOT fast-path.
174 capabilities_
.avoid_pow2_textures
=
175 extensions
.count("GL_CHROMIUM_fast_NPOT_MO8_textures") > 0;
177 capabilities_
.using_offscreen_context3d
= true;
179 is_using_bind_uniform_
=
180 extensions
.count("GL_CHROMIUM_bind_uniform_location") > 0;
182 // Make sure scissoring starts as disabled.
183 GLC(context_
, context_
->disable(GL_SCISSOR_TEST
));
184 DCHECK(!is_scissor_enabled_
);
186 if (!InitializeSharedObjects())
189 // Make sure the viewport and context gets initialized, even if it is to zero.
194 GLRenderer::~GLRenderer() {
195 context_
->setMemoryAllocationChangedCallbackCHROMIUM(NULL
);
196 CleanupSharedObjects();
199 const RendererCapabilities
& GLRenderer::Capabilities() const {
200 return capabilities_
;
203 WebGraphicsContext3D
* GLRenderer::Context() { return context_
; }
205 void GLRenderer::DebugGLCall(WebGraphicsContext3D
* context
,
209 unsigned error
= context
->getError();
210 if (error
!= GL_NO_ERROR
)
211 LOG(ERROR
) << "GL command failed: File: " << file
<< "\n\tLine " << line
212 << "\n\tcommand: " << command
<< ", error "
213 << static_cast<int>(error
) << "\n";
216 void GLRenderer::SetVisible(bool visible
) {
217 if (visible_
== visible
)
221 EnforceMemoryPolicy();
223 // TODO(jamesr): Replace setVisibilityCHROMIUM() with an extension to
224 // explicitly manage front/backbuffers
226 if (capabilities_
.using_set_visibility
)
227 context_
->setVisibilityCHROMIUM(visible
);
230 void GLRenderer::SendManagedMemoryStats(size_t bytes_visible
,
231 size_t bytes_visible_and_nearby
,
232 size_t bytes_allocated
) {
233 WebKit::WebGraphicsManagedMemoryStats stats
;
234 stats
.bytesVisible
= bytes_visible
;
235 stats
.bytesVisibleAndNearby
= bytes_visible_and_nearby
;
236 stats
.bytesAllocated
= bytes_allocated
;
237 stats
.backbufferRequested
= !is_backbuffer_discarded_
;
238 context_
->sendManagedMemoryStatsCHROMIUM(&stats
);
241 void GLRenderer::ReleaseRenderPassTextures() { render_pass_textures_
.clear(); }
243 void GLRenderer::ViewportChanged() { is_viewport_changed_
= true; }
245 void GLRenderer::ClearFramebuffer(DrawingFrame
* frame
) {
246 // On DEBUG builds, opaque render passes are cleared to blue to easily see
247 // regions that were not drawn on the screen.
248 if (frame
->current_render_pass
->has_transparent_background
)
249 GLC(context_
, context_
->clearColor(0, 0, 0, 0));
251 GLC(context_
, context_
->clearColor(0, 0, 1, 1));
254 if (frame
->current_render_pass
->has_transparent_background
)
256 context_
->clear(GL_COLOR_BUFFER_BIT
);
259 void GLRenderer::BeginDrawingFrame(DrawingFrame
* frame
) {
260 // FIXME: Remove this once backbuffer is automatically recreated on first use
263 if (ViewportSize().IsEmpty())
266 TRACE_EVENT0("cc", "GLRenderer::DrawLayers");
267 if (is_viewport_changed_
) {
268 // Only reshape when we know we are going to draw. Otherwise, the reshape
269 // can leave the window at the wrong size if we never draw and the proper
270 // viewport size is never set.
271 is_viewport_changed_
= false;
272 output_surface_
->Reshape(gfx::Size(ViewportWidth(), ViewportHeight()));
275 MakeContextCurrent();
276 // Bind the common vertex attributes used for drawing all the layers.
277 shared_geometry_
->PrepareForDraw();
279 GLC(context_
, context_
->disable(GL_DEPTH_TEST
));
280 GLC(context_
, context_
->disable(GL_CULL_FACE
));
281 GLC(context_
, context_
->colorMask(true, true, true, true));
282 GLC(context_
, context_
->enable(GL_BLEND
));
283 blend_shadow_
= true;
284 GLC(context_
, context_
->blendFunc(GL_ONE
, GL_ONE_MINUS_SRC_ALPHA
));
285 GLC(Context(), Context()->activeTexture(GL_TEXTURE0
));
289 void GLRenderer::DoNoOp() {
290 GLC(context_
, context_
->bindFramebuffer(GL_FRAMEBUFFER
, 0));
291 GLC(context_
, context_
->flush());
294 void GLRenderer::DoDrawQuad(DrawingFrame
* frame
, const DrawQuad
* quad
) {
295 DCHECK(quad
->rect
.Contains(quad
->visible_rect
));
296 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
) {
297 FlushTextureQuadCache();
300 switch (quad
->material
) {
301 case DrawQuad::INVALID
:
304 case DrawQuad::CHECKERBOARD
:
305 DrawCheckerboardQuad(frame
, CheckerboardDrawQuad::MaterialCast(quad
));
307 case DrawQuad::DEBUG_BORDER
:
308 DrawDebugBorderQuad(frame
, DebugBorderDrawQuad::MaterialCast(quad
));
310 case DrawQuad::IO_SURFACE_CONTENT
:
311 DrawIOSurfaceQuad(frame
, IOSurfaceDrawQuad::MaterialCast(quad
));
313 case DrawQuad::PICTURE_CONTENT
:
314 DrawPictureQuad(frame
, PictureDrawQuad::MaterialCast(quad
));
316 case DrawQuad::RENDER_PASS
:
317 DrawRenderPassQuad(frame
, RenderPassDrawQuad::MaterialCast(quad
));
319 case DrawQuad::SOLID_COLOR
:
320 DrawSolidColorQuad(frame
, SolidColorDrawQuad::MaterialCast(quad
));
322 case DrawQuad::STREAM_VIDEO_CONTENT
:
323 DrawStreamVideoQuad(frame
, StreamVideoDrawQuad::MaterialCast(quad
));
325 case DrawQuad::TEXTURE_CONTENT
:
326 EnqueueTextureQuad(frame
, TextureDrawQuad::MaterialCast(quad
));
328 case DrawQuad::TILED_CONTENT
:
329 DrawTileQuad(frame
, TileDrawQuad::MaterialCast(quad
));
331 case DrawQuad::YUV_VIDEO_CONTENT
:
332 DrawYUVVideoQuad(frame
, YUVVideoDrawQuad::MaterialCast(quad
));
337 void GLRenderer::DrawCheckerboardQuad(const DrawingFrame
* frame
,
338 const CheckerboardDrawQuad
* quad
) {
339 SetBlendEnabled(quad
->ShouldDrawWithBlending());
341 const TileCheckerboardProgram
* program
= GetTileCheckerboardProgram();
342 DCHECK(program
&& (program
->initialized() || IsContextLost()));
343 SetUseProgram(program
->program());
345 SkColor color
= quad
->color
;
347 Context()->uniform4f(program
->fragment_shader().color_location(),
348 SkColorGetR(color
) * (1.0f
/ 255.0f
),
349 SkColorGetG(color
) * (1.0f
/ 255.0f
),
350 SkColorGetB(color
) * (1.0f
/ 255.0f
),
353 const int checkerboard_width
= 16;
354 float frequency
= 1.0f
/ checkerboard_width
;
356 gfx::Rect tile_rect
= quad
->rect
;
357 float tex_offset_x
= tile_rect
.x() % checkerboard_width
;
358 float tex_offset_y
= tile_rect
.y() % checkerboard_width
;
359 float tex_scale_x
= tile_rect
.width();
360 float tex_scale_y
= tile_rect
.height();
362 Context()->uniform4f(program
->fragment_shader().tex_transform_location(),
369 Context()->uniform1f(program
->fragment_shader().frequency_location(),
372 SetShaderOpacity(quad
->opacity(),
373 program
->fragment_shader().alpha_location());
374 DrawQuadGeometry(frame
,
375 quad
->quadTransform(),
377 program
->vertex_shader().matrix_location());
380 void GLRenderer::DrawDebugBorderQuad(const DrawingFrame
* frame
,
381 const DebugBorderDrawQuad
* quad
) {
382 SetBlendEnabled(quad
->ShouldDrawWithBlending());
384 static float gl_matrix
[16];
385 const DebugBorderProgram
* program
= GetDebugBorderProgram();
386 DCHECK(program
&& (program
->initialized() || IsContextLost()));
387 SetUseProgram(program
->program());
389 // Use the full quad_rect for debug quads to not move the edges based on
391 gfx::Rect layer_rect
= quad
->rect
;
392 gfx::Transform render_matrix
= quad
->quadTransform();
393 render_matrix
.Translate(0.5f
* layer_rect
.width() + layer_rect
.x(),
394 0.5f
* layer_rect
.height() + layer_rect
.y());
395 render_matrix
.Scale(layer_rect
.width(), layer_rect
.height());
396 GLRenderer::ToGLMatrix(&gl_matrix
[0],
397 frame
->projection_matrix
* render_matrix
);
399 Context()->uniformMatrix4fv(
400 program
->vertex_shader().matrix_location(), 1, false, &gl_matrix
[0]));
402 SkColor color
= quad
->color
;
403 float alpha
= SkColorGetA(color
) * (1.0f
/ 255.0f
);
406 Context()->uniform4f(program
->fragment_shader().color_location(),
407 (SkColorGetR(color
) * (1.0f
/ 255.0f
)) * alpha
,
408 (SkColorGetG(color
) * (1.0f
/ 255.0f
)) * alpha
,
409 (SkColorGetB(color
) * (1.0f
/ 255.0f
)) * alpha
,
412 GLC(Context(), Context()->lineWidth(quad
->width
));
414 // The indices for the line are stored in the same array as the triangle
417 Context()->drawElements(GL_LINE_LOOP
, 4, GL_UNSIGNED_SHORT
, 0));
420 static inline SkBitmap
ApplyFilters(GLRenderer
* renderer
,
421 const WebKit::WebFilterOperations
& filters
,
422 ScopedResource
* source_texture_resource
) {
423 if (filters
.isEmpty())
426 ContextProvider
* offscreen_contexts
=
427 renderer
->resource_provider()->offscreen_context_provider();
428 if (!offscreen_contexts
|| !offscreen_contexts
->GrContext())
431 ResourceProvider::ScopedWriteLockGL
lock(renderer
->resource_provider(),
432 source_texture_resource
->id());
434 // Flush the compositor context to ensure that textures there are available
435 // in the shared context. Do this after locking/creating the compositor
437 renderer
->resource_provider()->Flush();
439 // Make sure skia uses the correct GL context.
440 offscreen_contexts
->Context3d()->makeContextCurrent();
443 RenderSurfaceFilters::Apply(filters
,
445 source_texture_resource
->size(),
446 offscreen_contexts
->GrContext());
448 // Flush skia context so that all the rendered stuff appears on the
450 offscreen_contexts
->GrContext()->flush();
452 // Flush the GL context so rendering results from this context are
453 // visible in the compositor's context.
454 offscreen_contexts
->Context3d()->flush();
456 // Use the compositor's GL context again.
457 renderer
->resource_provider()->GraphicsContext3D()->makeContextCurrent();
461 static SkBitmap
ApplyImageFilter(GLRenderer
* renderer
,
462 SkImageFilter
* filter
,
463 ScopedResource
* source_texture_resource
) {
467 ContextProvider
* offscreen_contexts
=
468 renderer
->resource_provider()->offscreen_context_provider();
469 if (!offscreen_contexts
|| !offscreen_contexts
->GrContext())
472 ResourceProvider::ScopedWriteLockGL
lock(renderer
->resource_provider(),
473 source_texture_resource
->id());
475 // Flush the compositor context to ensure that textures there are available
476 // in the shared context. Do this after locking/creating the compositor
478 renderer
->resource_provider()->Flush();
480 // Make sure skia uses the correct GL context.
481 offscreen_contexts
->Context3d()->makeContextCurrent();
483 // Wrap the source texture in a Ganesh platform texture.
484 GrBackendTextureDesc backend_texture_description
;
485 backend_texture_description
.fWidth
= source_texture_resource
->size().width();
486 backend_texture_description
.fHeight
=
487 source_texture_resource
->size().height();
488 backend_texture_description
.fConfig
= kSkia8888_GrPixelConfig
;
489 backend_texture_description
.fTextureHandle
= lock
.texture_id();
490 backend_texture_description
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
491 skia::RefPtr
<GrTexture
> texture
=
492 skia::AdoptRef(offscreen_contexts
->GrContext()->wrapBackendTexture(
493 backend_texture_description
));
495 // Place the platform texture inside an SkBitmap.
497 source
.setConfig(SkBitmap::kARGB_8888_Config
,
498 source_texture_resource
->size().width(),
499 source_texture_resource
->size().height());
500 skia::RefPtr
<SkGrPixelRef
> pixel_ref
=
501 skia::AdoptRef(new SkGrPixelRef(texture
.get()));
502 source
.setPixelRef(pixel_ref
.get());
504 // Create a scratch texture for backing store.
506 desc
.fFlags
= kRenderTarget_GrTextureFlagBit
| kNoStencil_GrTextureFlagBit
;
508 desc
.fWidth
= source
.width();
509 desc
.fHeight
= source
.height();
510 desc
.fConfig
= kSkia8888_GrPixelConfig
;
511 desc
.fOrigin
= kTopLeft_GrSurfaceOrigin
;
512 GrAutoScratchTexture
scratch_texture(
513 offscreen_contexts
->GrContext(), desc
, GrContext::kExact_ScratchTexMatch
);
514 skia::RefPtr
<GrTexture
> backing_store
=
515 skia::AdoptRef(scratch_texture
.detach());
517 // Create a device and canvas using that backing store.
518 SkGpuDevice
device(offscreen_contexts
->GrContext(), backing_store
.get());
519 SkCanvas
canvas(&device
);
521 // Draw the source bitmap through the filter to the canvas.
523 paint
.setImageFilter(filter
);
524 canvas
.clear(SK_ColorTRANSPARENT
);
525 canvas
.drawSprite(source
, 0, 0, &paint
);
527 // Flush skia context so that all the rendered stuff appears on the
529 offscreen_contexts
->GrContext()->flush();
531 // Flush the GL context so rendering results from this context are
532 // visible in the compositor's context.
533 offscreen_contexts
->Context3d()->flush();
535 // Use the compositor's GL context again.
536 renderer
->resource_provider()->GraphicsContext3D()->makeContextCurrent();
538 return device
.accessBitmap(false);
541 scoped_ptr
<ScopedResource
> GLRenderer::DrawBackgroundFilters(
543 const RenderPassDrawQuad
* quad
,
544 const gfx::Transform
& contents_device_transform
,
545 const gfx::Transform
& contents_device_transform_inverse
) {
546 // This method draws a background filter, which applies a filter to any pixels
547 // behind the quad and seen through its background. The algorithm works as
549 // 1. Compute a bounding box around the pixels that will be visible through
551 // 2. Read the pixels in the bounding box into a buffer R.
552 // 3. Apply the background filter to R, so that it is applied in the pixels'
554 // 4. Apply the quad's inverse transform to map the pixels in R into the
555 // quad's content space. This implicitly clips R by the content bounds of the
556 // quad since the destination texture has bounds matching the quad's content.
557 // 5. Draw the background texture for the contents using the same transform as
558 // used to draw the contents itself. This is done without blending to replace
559 // the current background pixels with the new filtered background.
560 // 6. Draw the contents of the quad over drop of the new background with
561 // blending, as per usual. The filtered background pixels will show through
562 // any non-opaque pixels in this draws.
564 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
566 // FIXME: When this algorithm changes, update
567 // LayerTreeHost::PrioritizeTextures() accordingly.
569 const WebKit::WebFilterOperations
& filters
= quad
->background_filters
;
570 DCHECK(!filters
.isEmpty());
572 // FIXME: We only allow background filters on an opaque render surface because
573 // other surfaces may contain translucent pixels, and the contents behind
574 // those translucent pixels wouldn't have the filter applied.
575 if (frame
->current_render_pass
->has_transparent_background
)
576 return scoped_ptr
<ScopedResource
>();
577 DCHECK(!frame
->current_texture
);
579 // FIXME: Do a single readback for both the surface and replica and cache the
580 // filtered results (once filter textures are not reused).
581 gfx::Rect device_rect
= gfx::ToEnclosingRect(MathUtil::MapClippedRect(
582 contents_device_transform
, SharedGeometryQuad().BoundingBox()));
584 int top
, right
, bottom
, left
;
585 filters
.getOutsets(top
, right
, bottom
, left
);
586 device_rect
.Inset(-left
, -top
, -right
, -bottom
);
588 device_rect
.Intersect(frame
->current_render_pass
->output_rect
);
590 scoped_ptr
<ScopedResource
> device_background_texture
=
591 ScopedResource::create(resource_provider_
);
592 if (!GetFramebufferTexture(device_background_texture
.get(), device_rect
))
593 return scoped_ptr
<ScopedResource
>();
595 SkBitmap filtered_device_background
=
596 ApplyFilters(this, filters
, device_background_texture
.get());
597 if (!filtered_device_background
.getTexture())
598 return scoped_ptr
<ScopedResource
>();
601 reinterpret_cast<GrTexture
*>(filtered_device_background
.getTexture());
602 int filtered_device_background_texture_id
= texture
->getTextureHandle();
604 scoped_ptr
<ScopedResource
> background_texture
=
605 ScopedResource::create(resource_provider_
);
606 if (!background_texture
->Allocate(quad
->rect
.size(),
608 ResourceProvider::TextureUsageFramebuffer
))
609 return scoped_ptr
<ScopedResource
>();
611 const RenderPass
* target_render_pass
= frame
->current_render_pass
;
612 bool using_background_texture
=
613 UseScopedTexture(frame
, background_texture
.get(), quad
->rect
);
615 if (using_background_texture
) {
616 // Copy the readback pixels from device to the background texture for the
618 gfx::Transform device_to_framebuffer_transform
;
619 device_to_framebuffer_transform
.Translate(
620 quad
->rect
.width() * 0.5f
+ quad
->rect
.x(),
621 quad
->rect
.height() * 0.5f
+ quad
->rect
.y());
622 device_to_framebuffer_transform
.Scale(quad
->rect
.width(),
623 quad
->rect
.height());
624 device_to_framebuffer_transform
.PreconcatTransform(
625 contents_device_transform_inverse
);
628 GLC(Context(), Context()->clearColor(0, 0, 1, 1));
629 Context()->clear(GL_COLOR_BUFFER_BIT
);
632 CopyTextureToFramebuffer(frame
,
633 filtered_device_background_texture_id
,
635 device_to_framebuffer_transform
);
638 UseRenderPass(frame
, target_render_pass
);
640 if (!using_background_texture
)
641 return scoped_ptr
<ScopedResource
>();
642 return background_texture
.Pass();
645 void GLRenderer::DrawRenderPassQuad(DrawingFrame
* frame
,
646 const RenderPassDrawQuad
* quad
) {
647 SetBlendEnabled(quad
->ShouldDrawWithBlending());
649 CachedResource
* contents_texture
=
650 render_pass_textures_
.get(quad
->render_pass_id
);
651 if (!contents_texture
|| !contents_texture
->id())
654 gfx::Transform quad_rect_matrix
;
655 QuadRectTransform(&quad_rect_matrix
, quad
->quadTransform(), quad
->rect
);
656 gfx::Transform contents_device_transform
=
657 frame
->window_matrix
* frame
->projection_matrix
* quad_rect_matrix
;
658 contents_device_transform
.FlattenTo2d();
660 // Can only draw surface if device matrix is invertible.
661 gfx::Transform
contents_device_transform_inverse(
662 gfx::Transform::kSkipInitialization
);
663 if (!contents_device_transform
.GetInverse(&contents_device_transform_inverse
))
666 scoped_ptr
<ScopedResource
> background_texture
;
667 if (!quad
->background_filters
.isEmpty()) {
668 // The pixels from the filtered background should completely replace the
669 // current pixel values.
670 bool disable_blending
= blend_enabled();
671 if (disable_blending
)
672 SetBlendEnabled(false);
674 background_texture
= DrawBackgroundFilters(
677 contents_device_transform
,
678 contents_device_transform_inverse
);
680 if (disable_blending
)
681 SetBlendEnabled(true);
684 // FIXME: Cache this value so that we don't have to do it for both the surface
685 // and its replica. Apply filters to the contents texture.
686 SkBitmap filter_bitmap
;
687 SkScalar color_matrix
[20];
688 bool use_color_matrix
= false;
691 if ((quad
->filter
->asColorFilter(&cf
)) && cf
->asColorMatrix(color_matrix
) &&
692 !quad
->filter
->getInput(0)) {
693 // We have a single color matrix as a filter; apply it locally
694 // in the compositor.
695 use_color_matrix
= true;
698 ApplyImageFilter(this, quad
->filter
.get(), contents_texture
);
701 filter_bitmap
= ApplyFilters(this, quad
->filters
, contents_texture
);
704 // Draw the background texture if there is one.
705 if (background_texture
) {
706 DCHECK(background_texture
->size() == quad
->rect
.size());
707 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
,
708 background_texture
->id());
709 CopyTextureToFramebuffer(
710 frame
, lock
.texture_id(), quad
->rect
, quad
->quadTransform());
713 bool clipped
= false;
714 gfx::QuadF device_quad
= MathUtil::MapQuad(
715 contents_device_transform
, SharedGeometryQuad(), &clipped
);
717 LayerQuad
device_layer_bounds(gfx::QuadF(device_quad
.BoundingBox()));
718 LayerQuad
device_layer_edges(device_quad
);
720 // Use anti-aliasing programs only when necessary.
721 bool use_aa
= (!device_quad
.IsRectilinear() ||
722 !gfx::IsNearestRectWithinDistance(device_quad
.BoundingBox(),
723 kAntiAliasingEpsilon
));
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 tex_coord_precision
= 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(tex_coord_precision
);
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(tex_coord_precision
);
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(tex_coord_precision
);
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(tex_coord_precision
);
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(tex_coord_precision
);
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(tex_coord_precision
);
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(tex_coord_precision
);
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(tex_coord_precision
);
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 bool is_axis_aligned_in_target
= device_layer_quad
.IsRectilinear();
1020 bool is_nearest_rect_within_epsilon
= is_axis_aligned_in_target
&&
1021 gfx::IsNearestRectWithinDistance(device_layer_quad
.BoundingBox(),
1022 kAntiAliasingEpsilon
);
1023 bool use_aa
= !clipped
&& !is_nearest_rect_within_epsilon
&& 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 float tex_clamp_x
= std::min(
1209 0.5f
, 0.5f
* clamp_tex_rect
.width() - kAntiAliasingEpsilon
);
1210 float tex_clamp_y
= std::min(
1211 0.5f
, 0.5f
* clamp_tex_rect
.height() - kAntiAliasingEpsilon
);
1212 float geom_clamp_x
= std::min(
1213 tex_clamp_x
* tex_to_geom_scale_x
,
1214 0.5f
* clamp_geom_rect
.width() - kAntiAliasingEpsilon
);
1215 float geom_clamp_y
= std::min(
1216 tex_clamp_y
* tex_to_geom_scale_y
,
1217 0.5f
* clamp_geom_rect
.height() - kAntiAliasingEpsilon
);
1218 clamp_geom_rect
.Inset(geom_clamp_x
, geom_clamp_y
, geom_clamp_x
, geom_clamp_y
);
1219 clamp_tex_rect
.Inset(tex_clamp_x
, tex_clamp_y
, tex_clamp_x
, tex_clamp_y
);
1221 // Map clamping rectangle to unit square.
1222 float vertex_tex_translate_x
= -clamp_geom_rect
.x() / clamp_geom_rect
.width();
1223 float vertex_tex_translate_y
=
1224 -clamp_geom_rect
.y() / clamp_geom_rect
.height();
1225 float vertex_tex_scale_x
= tile_rect
.width() / clamp_geom_rect
.width();
1226 float vertex_tex_scale_y
= tile_rect
.height() / clamp_geom_rect
.height();
1228 TexCoordPrecision tex_coord_precision
= TexCoordPrecisionRequired(
1229 context_
, highp_threshold_min_
, quad
->texture_size
);
1231 // Map to normalized texture coordinates.
1232 gfx::Size texture_size
= quad
->texture_size
;
1233 float fragment_tex_translate_x
= clamp_tex_rect
.x() / texture_size
.width();
1234 float fragment_tex_translate_y
= clamp_tex_rect
.y() / texture_size
.height();
1235 float fragment_tex_scale_x
= clamp_tex_rect
.width() / texture_size
.width();
1236 float fragment_tex_scale_y
= clamp_tex_rect
.height() / texture_size
.height();
1238 gfx::Transform device_transform
=
1239 frame
->window_matrix
* frame
->projection_matrix
* quad
->quadTransform();
1240 device_transform
.FlattenTo2d();
1241 if (!device_transform
.IsInvertible())
1244 gfx::QuadF local_quad
= gfx::QuadF(gfx::RectF(tile_rect
));
1246 bool use_aa
= SetupQuadForAntialiasing(
1247 device_transform
, quad
, &local_quad
, edge
);
1249 TileProgramUniforms uniforms
;
1251 if (quad
->swizzle_contents
) {
1252 TileUniformLocation(GetTileProgramSwizzleAA(tex_coord_precision
),
1255 TileUniformLocation(GetTileProgramAA(tex_coord_precision
), &uniforms
);
1258 if (quad
->ShouldDrawWithBlending()) {
1259 if (quad
->swizzle_contents
) {
1260 TileUniformLocation(GetTileProgramSwizzle(tex_coord_precision
),
1263 TileUniformLocation(GetTileProgram(tex_coord_precision
), &uniforms
);
1266 if (quad
->swizzle_contents
) {
1267 TileUniformLocation(GetTileProgramSwizzleOpaque(tex_coord_precision
),
1270 TileUniformLocation(GetTileProgramOpaque(tex_coord_precision
),
1276 SetUseProgram(uniforms
.program
);
1277 GLC(Context(), Context()->uniform1i(uniforms
.sampler_location
, 0));
1278 bool scaled
= (tex_to_geom_scale_x
!= 1.f
|| tex_to_geom_scale_y
!= 1.f
);
1279 GLenum filter
= (use_aa
|| scaled
||
1280 !quad
->quadTransform().IsIdentityOrIntegerTranslation())
1283 ResourceProvider::ScopedSamplerGL
quad_resource_lock(
1284 resource_provider_
, resource_id
, GL_TEXTURE_2D
, filter
);
1287 GLC(Context(), Context()->uniform3fv(uniforms
.edge_location
, 8, edge
));
1290 Context()->uniform4f(uniforms
.vertex_tex_transform_location
,
1291 vertex_tex_translate_x
,
1292 vertex_tex_translate_y
,
1294 vertex_tex_scale_y
));
1296 Context()->uniform4f(uniforms
.fragment_tex_transform_location
,
1297 fragment_tex_translate_x
,
1298 fragment_tex_translate_y
,
1299 fragment_tex_scale_x
,
1300 fragment_tex_scale_y
));
1302 // Move fragment shader transform to vertex shader. We can do this while
1303 // still producing correct results as fragment_tex_transform_location
1304 // should always be non-negative when tiles are transformed in a way
1305 // that could result in sampling outside the layer.
1306 vertex_tex_scale_x
*= fragment_tex_scale_x
;
1307 vertex_tex_scale_y
*= fragment_tex_scale_y
;
1308 vertex_tex_translate_x
*= fragment_tex_scale_x
;
1309 vertex_tex_translate_y
*= fragment_tex_scale_y
;
1310 vertex_tex_translate_x
+= fragment_tex_translate_x
;
1311 vertex_tex_translate_y
+= fragment_tex_translate_y
;
1314 Context()->uniform4f(uniforms
.vertex_tex_transform_location
,
1315 vertex_tex_translate_x
,
1316 vertex_tex_translate_y
,
1318 vertex_tex_scale_y
));
1321 // Enable blending when the quad properties require it or if we decided
1322 // to use antialiasing.
1323 SetBlendEnabled(quad
->ShouldDrawWithBlending() || use_aa
);
1325 // Normalize to tile_rect.
1326 local_quad
.Scale(1.0f
/ tile_rect
.width(), 1.0f
/ tile_rect
.height());
1328 SetShaderOpacity(quad
->opacity(), uniforms
.alpha_location
);
1329 SetShaderQuadF(local_quad
, uniforms
.point_location
);
1331 // The transform and vertex data are used to figure out the extents that the
1332 // un-antialiased quad should have and which vertex this is and the float
1333 // quad passed in via uniform is the actual geometry that gets used to draw
1334 // it. This is why this centered rect is used and not the original quad_rect.
1335 gfx::RectF
centered_rect(
1336 gfx::PointF(-0.5f
* tile_rect
.width(), -0.5f
* tile_rect
.height()),
1339 frame
, quad
->quadTransform(), centered_rect
, uniforms
.matrix_location
);
1342 void GLRenderer::DrawYUVVideoQuad(const DrawingFrame
* frame
,
1343 const YUVVideoDrawQuad
* quad
) {
1344 SetBlendEnabled(quad
->ShouldDrawWithBlending());
1346 TexCoordPrecision tex_coord_precision
= TexCoordPrecisionRequired(
1347 context_
, highp_threshold_min_
,
1348 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1350 const VideoYUVProgram
* program
= GetVideoYUVProgram(tex_coord_precision
);
1351 DCHECK(program
&& (program
->initialized() || IsContextLost()));
1353 GLC(Context(), Context()->activeTexture(GL_TEXTURE1
));
1354 ResourceProvider::ScopedSamplerGL
y_plane_lock(
1355 resource_provider_
, quad
->y_plane_resource_id
, GL_TEXTURE_2D
, GL_LINEAR
);
1356 GLC(Context(), Context()->activeTexture(GL_TEXTURE2
));
1357 ResourceProvider::ScopedSamplerGL
u_plane_lock(
1358 resource_provider_
, quad
->u_plane_resource_id
, GL_TEXTURE_2D
, GL_LINEAR
);
1359 GLC(Context(), Context()->activeTexture(GL_TEXTURE3
));
1360 ResourceProvider::ScopedSamplerGL
v_plane_lock(
1361 resource_provider_
, quad
->v_plane_resource_id
, GL_TEXTURE_2D
, GL_LINEAR
);
1363 SetUseProgram(program
->program());
1366 Context()->uniform2f(program
->vertex_shader().tex_scale_location(),
1367 quad
->tex_scale
.width(),
1368 quad
->tex_scale
.height()));
1370 Context()->uniform1i(program
->fragment_shader().y_texture_location(), 1));
1372 Context()->uniform1i(program
->fragment_shader().u_texture_location(), 2));
1374 Context()->uniform1i(program
->fragment_shader().v_texture_location(), 3));
1376 // These values are magic numbers that are used in the transformation from YUV
1377 // to RGB color values. They are taken from the following webpage:
1378 // http://www.fourcc.org/fccyvrgb.php
1379 float yuv_to_rgb
[9] = {
1380 1.164f
, 1.164f
, 1.164f
,
1381 0.0f
, -.391f
, 2.018f
,
1382 1.596f
, -.813f
, 0.0f
,
1385 Context()->uniformMatrix3fv(
1386 program
->fragment_shader().yuv_matrix_location(), 1, 0, yuv_to_rgb
));
1388 // These values map to 16, 128, and 128 respectively, and are computed
1389 // as a fraction over 256 (e.g. 16 / 256 = 0.0625).
1390 // They are used in the YUV to RGBA conversion formula:
1391 // Y - 16 : Gives 16 values of head and footroom for overshooting
1392 // U - 128 : Turns unsigned U into signed U [-128,127]
1393 // V - 128 : Turns unsigned V into signed V [-128,127]
1394 float yuv_adjust
[3] = { -0.0625f
, -0.5f
, -0.5f
, };
1396 Context()->uniform3fv(
1397 program
->fragment_shader().yuv_adj_location(), 1, yuv_adjust
));
1399 SetShaderOpacity(quad
->opacity(),
1400 program
->fragment_shader().alpha_location());
1401 DrawQuadGeometry(frame
,
1402 quad
->quadTransform(),
1404 program
->vertex_shader().matrix_location());
1406 // Reset active texture back to texture 0.
1407 GLC(Context(), Context()->activeTexture(GL_TEXTURE0
));
1410 void GLRenderer::DrawStreamVideoQuad(const DrawingFrame
* frame
,
1411 const StreamVideoDrawQuad
* quad
) {
1412 SetBlendEnabled(quad
->ShouldDrawWithBlending());
1414 static float gl_matrix
[16];
1416 DCHECK(capabilities_
.using_egl_image
);
1418 TexCoordPrecision tex_coord_precision
= TexCoordPrecisionRequired(
1419 context_
, highp_threshold_min_
,
1420 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1422 const VideoStreamTextureProgram
* program
=
1423 GetVideoStreamTextureProgram(tex_coord_precision
);
1424 SetUseProgram(program
->program());
1426 ToGLMatrix(&gl_matrix
[0], quad
->matrix
);
1428 Context()->uniformMatrix4fv(
1429 program
->vertex_shader().tex_matrix_location(), 1, false, gl_matrix
));
1431 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
,
1434 Context()->bindTexture(GL_TEXTURE_EXTERNAL_OES
, lock
.texture_id()));
1437 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
1439 SetShaderOpacity(quad
->opacity(),
1440 program
->fragment_shader().alpha_location());
1441 DrawQuadGeometry(frame
,
1442 quad
->quadTransform(),
1444 program
->vertex_shader().matrix_location());
1447 void GLRenderer::DrawPictureQuad(const DrawingFrame
* frame
,
1448 const PictureDrawQuad
* quad
) {
1449 if (on_demand_tile_raster_bitmap_
.width() != quad
->texture_size
.width() ||
1450 on_demand_tile_raster_bitmap_
.height() != quad
->texture_size
.height()) {
1451 on_demand_tile_raster_bitmap_
.setConfig(
1452 SkBitmap::kARGB_8888_Config
,
1453 quad
->texture_size
.width(),
1454 quad
->texture_size
.height());
1455 on_demand_tile_raster_bitmap_
.allocPixels();
1457 if (on_demand_tile_raster_resource_id_
)
1458 resource_provider_
->DeleteResource(on_demand_tile_raster_resource_id_
);
1460 on_demand_tile_raster_resource_id_
= resource_provider_
->CreateGLTexture(
1463 GL_TEXTURE_POOL_UNMANAGED_CHROMIUM
,
1464 ResourceProvider::TextureUsageAny
);
1467 SkDevice
device(on_demand_tile_raster_bitmap_
);
1468 SkCanvas
canvas(&device
);
1470 quad
->picture_pile
->Raster(&canvas
, quad
->content_rect
, quad
->contents_scale
,
1473 resource_provider_
->SetPixels(
1474 on_demand_tile_raster_resource_id_
,
1475 reinterpret_cast<uint8_t*>(on_demand_tile_raster_bitmap_
.getPixels()),
1476 gfx::Rect(quad
->texture_size
),
1477 gfx::Rect(quad
->texture_size
),
1480 DrawContentQuad(frame
, quad
, on_demand_tile_raster_resource_id_
);
1483 struct TextureProgramBinding
{
1484 template <class Program
>
1485 void Set(Program
* program
, WebKit::WebGraphicsContext3D
* context
) {
1486 DCHECK(program
&& (program
->initialized() || context
->isContextLost()));
1487 program_id
= program
->program();
1488 sampler_location
= program
->fragment_shader().sampler_location();
1489 matrix_location
= program
->vertex_shader().matrix_location();
1490 alpha_location
= program
->fragment_shader().alpha_location();
1493 int sampler_location
;
1494 int matrix_location
;
1498 struct TexTransformTextureProgramBinding
: TextureProgramBinding
{
1499 template <class Program
>
1500 void Set(Program
* program
, WebKit::WebGraphicsContext3D
* context
) {
1501 TextureProgramBinding::Set(program
, context
);
1502 tex_transform_location
= program
->vertex_shader().tex_transform_location();
1503 vertex_opacity_location
=
1504 program
->vertex_shader().vertex_opacity_location();
1506 int tex_transform_location
;
1507 int vertex_opacity_location
;
1510 void GLRenderer::FlushTextureQuadCache() {
1511 // Check to see if we have anything to draw.
1512 if (draw_cache_
.program_id
== 0)
1515 // Set the correct blending mode.
1516 SetBlendEnabled(draw_cache_
.needs_blending
);
1518 // Bind the program to the GL state.
1519 SetUseProgram(draw_cache_
.program_id
);
1521 // Bind the correct texture sampler location.
1522 GLC(Context(), Context()->uniform1i(draw_cache_
.sampler_location
, 0));
1524 // Assume the current active textures is 0.
1525 ResourceProvider::ScopedReadLockGL
locked_quad(resource_provider_
,
1526 draw_cache_
.resource_id
);
1528 Context()->bindTexture(GL_TEXTURE_2D
, locked_quad
.texture_id()));
1530 // set up premultiplied alpha.
1531 if (!draw_cache_
.use_premultiplied_alpha
) {
1532 // As it turns out, the premultiplied alpha blending function (ONE,
1533 // ONE_MINUS_SRC_ALPHA) will never cause the alpha channel to be set to
1534 // anything less than 1.0f if it is initialized to that value! Therefore,
1535 // premultiplied_alpha being false is the first situation we can generally
1536 // see an alpha channel less than 1.0f coming out of the compositor. This is
1537 // causing platform differences in some layout tests (see
1538 // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use
1539 // a separate blend function for the alpha channel to avoid modifying it.
1540 // Don't use colorMask() for this as it has performance implications on some
1543 Context()->blendFuncSeparate(
1544 GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
, GL_ZERO
, GL_ONE
));
1548 sizeof(Float4
) == 4 * sizeof(float), // NOLINT(runtime/sizeof)
1549 struct_is_densely_packed
);
1551 sizeof(Float16
) == 16 * sizeof(float), // NOLINT(runtime/sizeof)
1552 struct_is_densely_packed
);
1554 // Upload the tranforms for both points and uvs.
1556 context_
->uniformMatrix4fv(
1557 static_cast<int>(draw_cache_
.matrix_location
),
1558 static_cast<int>(draw_cache_
.matrix_data
.size()),
1560 reinterpret_cast<float*>(&draw_cache_
.matrix_data
.front())));
1562 context_
->uniform4fv(
1563 static_cast<int>(draw_cache_
.uv_xform_location
),
1564 static_cast<int>(draw_cache_
.uv_xform_data
.size()),
1565 reinterpret_cast<float*>(&draw_cache_
.uv_xform_data
.front())));
1567 context_
->uniform1fv(
1568 static_cast<int>(draw_cache_
.vertex_opacity_location
),
1569 static_cast<int>(draw_cache_
.vertex_opacity_data
.size()),
1570 static_cast<float*>(&draw_cache_
.vertex_opacity_data
.front())));
1574 context_
->drawElements(GL_TRIANGLES
,
1575 6 * draw_cache_
.matrix_data
.size(),
1579 // Clean up after ourselves (reset state set above).
1580 if (!draw_cache_
.use_premultiplied_alpha
)
1581 GLC(context_
, context_
->blendFunc(GL_ONE
, GL_ONE_MINUS_SRC_ALPHA
));
1584 draw_cache_
.program_id
= 0;
1585 draw_cache_
.uv_xform_data
.resize(0);
1586 draw_cache_
.vertex_opacity_data
.resize(0);
1587 draw_cache_
.matrix_data
.resize(0);
1590 void GLRenderer::EnqueueTextureQuad(const DrawingFrame
* frame
,
1591 const TextureDrawQuad
* quad
) {
1592 TexCoordPrecision tex_coord_precision
= TexCoordPrecisionRequired(
1593 context_
, highp_threshold_min_
,
1594 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1596 // Choose the correct texture program binding
1597 TexTransformTextureProgramBinding binding
;
1599 binding
.Set(GetTextureProgramFlip(tex_coord_precision
), Context());
1601 binding
.Set(GetTextureProgram(tex_coord_precision
), Context());
1603 int resource_id
= quad
->resource_id
;
1605 if (draw_cache_
.program_id
!= binding
.program_id
||
1606 draw_cache_
.resource_id
!= resource_id
||
1607 draw_cache_
.use_premultiplied_alpha
!= quad
->premultiplied_alpha
||
1608 draw_cache_
.needs_blending
!= quad
->ShouldDrawWithBlending() ||
1609 draw_cache_
.matrix_data
.size() >= 8) {
1610 FlushTextureQuadCache();
1611 draw_cache_
.program_id
= binding
.program_id
;
1612 draw_cache_
.resource_id
= resource_id
;
1613 draw_cache_
.use_premultiplied_alpha
= quad
->premultiplied_alpha
;
1614 draw_cache_
.needs_blending
= quad
->ShouldDrawWithBlending();
1616 draw_cache_
.uv_xform_location
= binding
.tex_transform_location
;
1617 draw_cache_
.vertex_opacity_location
= binding
.vertex_opacity_location
;
1618 draw_cache_
.matrix_location
= binding
.matrix_location
;
1619 draw_cache_
.sampler_location
= binding
.sampler_location
;
1622 // Generate the uv-transform
1623 gfx::PointF uv0
= quad
->uv_top_left
;
1624 gfx::PointF uv1
= quad
->uv_bottom_right
;
1625 Float4 uv
= { { uv0
.x(), uv0
.y(), uv1
.x() - uv0
.x(), uv1
.y() - uv0
.y() } };
1626 draw_cache_
.uv_xform_data
.push_back(uv
);
1628 // Generate the vertex opacity
1629 const float opacity
= quad
->opacity();
1630 draw_cache_
.vertex_opacity_data
.push_back(quad
->vertex_opacity
[0] * opacity
);
1631 draw_cache_
.vertex_opacity_data
.push_back(quad
->vertex_opacity
[1] * opacity
);
1632 draw_cache_
.vertex_opacity_data
.push_back(quad
->vertex_opacity
[2] * opacity
);
1633 draw_cache_
.vertex_opacity_data
.push_back(quad
->vertex_opacity
[3] * opacity
);
1635 // Generate the transform matrix
1636 gfx::Transform quad_rect_matrix
;
1637 QuadRectTransform(&quad_rect_matrix
, quad
->quadTransform(), quad
->rect
);
1638 quad_rect_matrix
= frame
->projection_matrix
* quad_rect_matrix
;
1641 quad_rect_matrix
.matrix().asColMajorf(m
.data
);
1642 draw_cache_
.matrix_data
.push_back(m
);
1645 void GLRenderer::DrawTextureQuad(const DrawingFrame
* frame
,
1646 const TextureDrawQuad
* quad
) {
1647 TexCoordPrecision tex_coord_precision
= TexCoordPrecisionRequired(
1648 context_
, highp_threshold_min_
,
1649 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1651 TexTransformTextureProgramBinding binding
;
1653 binding
.Set(GetTextureProgramFlip(tex_coord_precision
), Context());
1655 binding
.Set(GetTextureProgram(tex_coord_precision
), Context());
1656 SetUseProgram(binding
.program_id
);
1657 GLC(Context(), Context()->uniform1i(binding
.sampler_location
, 0));
1658 gfx::PointF uv0
= quad
->uv_top_left
;
1659 gfx::PointF uv1
= quad
->uv_bottom_right
;
1661 Context()->uniform4f(binding
.tex_transform_location
,
1665 uv1
.y() - uv0
.y()));
1668 Context()->uniform1fv(
1669 binding
.vertex_opacity_location
, 4, quad
->vertex_opacity
));
1671 ResourceProvider::ScopedSamplerGL
quad_resource_lock(
1672 resource_provider_
, quad
->resource_id
, GL_TEXTURE_2D
, GL_LINEAR
);
1674 if (!quad
->premultiplied_alpha
) {
1675 // As it turns out, the premultiplied alpha blending function (ONE,
1676 // ONE_MINUS_SRC_ALPHA) will never cause the alpha channel to be set to
1677 // anything less than 1.0f if it is initialized to that value! Therefore,
1678 // premultiplied_alpha being false is the first situation we can generally
1679 // see an alpha channel less than 1.0f coming out of the compositor. This is
1680 // causing platform differences in some layout tests (see
1681 // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use
1682 // a separate blend function for the alpha channel to avoid modifying it.
1683 // Don't use colorMask() for this as it has performance implications on some
1686 Context()->blendFuncSeparate(
1687 GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
, GL_ZERO
, GL_ONE
));
1691 frame
, quad
->quadTransform(), quad
->rect
, binding
.matrix_location
);
1693 if (!quad
->premultiplied_alpha
)
1694 GLC(context_
, context_
->blendFunc(GL_ONE
, GL_ONE_MINUS_SRC_ALPHA
));
1697 void GLRenderer::DrawIOSurfaceQuad(const DrawingFrame
* frame
,
1698 const IOSurfaceDrawQuad
* quad
) {
1699 SetBlendEnabled(quad
->ShouldDrawWithBlending());
1701 TexCoordPrecision tex_coord_precision
= TexCoordPrecisionRequired(
1702 context_
, highp_threshold_min_
,
1703 quad
->shared_quad_state
->visible_content_rect
.bottom_right());
1705 TexTransformTextureProgramBinding binding
;
1706 binding
.Set(GetTextureIOSurfaceProgram(tex_coord_precision
), Context());
1708 SetUseProgram(binding
.program_id
);
1709 GLC(Context(), Context()->uniform1i(binding
.sampler_location
, 0));
1710 if (quad
->orientation
== IOSurfaceDrawQuad::FLIPPED
) {
1712 Context()->uniform4f(binding
.tex_transform_location
,
1714 quad
->io_surface_size
.height(),
1715 quad
->io_surface_size
.width(),
1716 quad
->io_surface_size
.height() * -1.0f
));
1719 Context()->uniform4f(binding
.tex_transform_location
,
1722 quad
->io_surface_size
.width(),
1723 quad
->io_surface_size
.height()));
1726 const float vertex_opacity
[] = { quad
->opacity(), quad
->opacity(),
1727 quad
->opacity(), quad
->opacity() };
1729 Context()->uniform1fv(
1730 binding
.vertex_opacity_location
, 4, vertex_opacity
));
1732 ResourceProvider::ScopedReadLockGL
lock(resource_provider_
,
1733 quad
->io_surface_resource_id
);
1735 Context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB
,
1736 lock
.texture_id()));
1739 frame
, quad
->quadTransform(), quad
->rect
, binding
.matrix_location
);
1741 GLC(Context(), Context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0));
1744 void GLRenderer::FinishDrawingFrame(DrawingFrame
* frame
) {
1745 current_framebuffer_lock_
.reset();
1746 swap_buffer_rect_
.Union(gfx::ToEnclosingRect(frame
->root_damage_rect
));
1748 GLC(context_
, context_
->disable(GL_BLEND
));
1749 blend_shadow_
= false;
1751 if (Settings().compositor_frame_message
) {
1752 CompositorFrame compositor_frame
;
1753 compositor_frame
.metadata
= client_
->MakeCompositorFrameMetadata();
1754 output_surface_
->SendFrameToParentCompositor(&compositor_frame
);
1758 void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(); }
1760 bool GLRenderer::FlippedFramebuffer() const { return true; }
1762 void GLRenderer::EnsureScissorTestEnabled() {
1763 if (is_scissor_enabled_
)
1766 FlushTextureQuadCache();
1767 GLC(context_
, context_
->enable(GL_SCISSOR_TEST
));
1768 is_scissor_enabled_
= true;
1771 void GLRenderer::EnsureScissorTestDisabled() {
1772 if (!is_scissor_enabled_
)
1775 FlushTextureQuadCache();
1776 GLC(context_
, context_
->disable(GL_SCISSOR_TEST
));
1777 is_scissor_enabled_
= false;
1780 void GLRenderer::CopyCurrentRenderPassToBitmap(DrawingFrame
* frame
,
1782 gfx::Size render_pass_size
= frame
->current_render_pass
->output_rect
.size();
1783 bitmap
->setConfig(SkBitmap::kARGB_8888_Config
,
1784 render_pass_size
.width(),
1785 render_pass_size
.height());
1786 if (bitmap
->allocPixels()) {
1787 bitmap
->lockPixels();
1788 GetFramebufferPixels(bitmap
->getPixels(), gfx::Rect(render_pass_size
));
1789 bitmap
->unlockPixels();
1793 void GLRenderer::ToGLMatrix(float* gl_matrix
, const gfx::Transform
& transform
) {
1794 transform
.matrix().asColMajorf(gl_matrix
);
1797 void GLRenderer::SetShaderQuadF(const gfx::QuadF
& quad
, int quad_location
) {
1798 if (quad_location
== -1)
1802 point
[0] = quad
.p1().x();
1803 point
[1] = quad
.p1().y();
1804 point
[2] = quad
.p2().x();
1805 point
[3] = quad
.p2().y();
1806 point
[4] = quad
.p3().x();
1807 point
[5] = quad
.p3().y();
1808 point
[6] = quad
.p4().x();
1809 point
[7] = quad
.p4().y();
1810 GLC(context_
, context_
->uniform2fv(quad_location
, 4, point
));
1813 void GLRenderer::SetShaderOpacity(float opacity
, int alpha_location
) {
1814 if (alpha_location
!= -1)
1815 GLC(context_
, context_
->uniform1f(alpha_location
, opacity
));
1818 void GLRenderer::SetBlendEnabled(bool enabled
) {
1819 if (enabled
== blend_shadow_
)
1823 GLC(context_
, context_
->enable(GL_BLEND
));
1825 GLC(context_
, context_
->disable(GL_BLEND
));
1826 blend_shadow_
= enabled
;
1829 void GLRenderer::SetUseProgram(unsigned program
) {
1830 if (program
== program_shadow_
)
1832 GLC(context_
, context_
->useProgram(program
));
1833 program_shadow_
= program
;
1836 void GLRenderer::DrawQuadGeometry(const DrawingFrame
* frame
,
1837 const gfx::Transform
& draw_transform
,
1838 const gfx::RectF
& quad_rect
,
1839 int matrix_location
) {
1840 gfx::Transform quad_rect_matrix
;
1841 QuadRectTransform(&quad_rect_matrix
, draw_transform
, quad_rect
);
1842 static float gl_matrix
[16];
1843 ToGLMatrix(&gl_matrix
[0], frame
->projection_matrix
* quad_rect_matrix
);
1845 context_
->uniformMatrix4fv(matrix_location
, 1, false, &gl_matrix
[0]));
1847 GLC(context_
, context_
->drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0));
1850 void GLRenderer::CopyTextureToFramebuffer(const DrawingFrame
* frame
,
1853 const gfx::Transform
& draw_matrix
) {
1854 TexCoordPrecision tex_coord_precision
= TexCoordPrecisionRequired(
1855 context_
, highp_threshold_min_
, rect
.bottom_right());
1856 const RenderPassProgram
* program
= GetRenderPassProgram(tex_coord_precision
);
1858 GLC(Context(), Context()->bindTexture(GL_TEXTURE_2D
, texture_id
));
1860 SetUseProgram(program
->program());
1862 Context()->uniform1i(program
->fragment_shader().sampler_location(), 0));
1864 Context()->uniform4f(program
->vertex_shader().tex_transform_location(),
1869 SetShaderOpacity(1, program
->fragment_shader().alpha_location());
1871 frame
, draw_matrix
, rect
, program
->vertex_shader().matrix_location());
1874 void GLRenderer::Finish() {
1875 TRACE_EVENT0("cc", "GLRenderer::finish");
1879 void GLRenderer::SwapBuffers(const LatencyInfo
& latency_info
) {
1881 DCHECK(!is_backbuffer_discarded_
);
1883 TRACE_EVENT0("cc", "GLRenderer::SwapBuffers");
1884 // We're done! Time to swapbuffers!
1886 if (capabilities_
.using_partial_swap
&& client_
->AllowPartialSwap()) {
1887 // If supported, we can save significant bandwidth by only swapping the
1888 // damaged/scissored region (clamped to the viewport)
1889 swap_buffer_rect_
.Intersect(gfx::Rect(ViewportSize()));
1890 int flipped_y_pos_of_rect_bottom
=
1891 ViewportHeight() - swap_buffer_rect_
.y() - swap_buffer_rect_
.height();
1892 output_surface_
->PostSubBuffer(gfx::Rect(swap_buffer_rect_
.x(),
1893 flipped_y_pos_of_rect_bottom
,
1894 swap_buffer_rect_
.width(),
1895 swap_buffer_rect_
.height()),
1898 output_surface_
->SwapBuffers(latency_info
);
1901 swap_buffer_rect_
= gfx::Rect();
1903 // We don't have real fences, so we mark read fences as passed
1904 // assuming a double-buffered GPU pipeline. A texture can be
1905 // written to after one full frame has past since it was last read.
1906 if (last_swap_fence_
)
1907 static_cast<SimpleSwapFence
*>(last_swap_fence_
.get())->SetHasPassed();
1908 last_swap_fence_
= resource_provider_
->GetReadLockFence();
1909 resource_provider_
->SetReadLockFence(new SimpleSwapFence());
1912 void GLRenderer::onMemoryAllocationChanged(
1913 WebGraphicsMemoryAllocation allocation
) {
1914 // Just ignore the memory manager when it says to set the limit to zero
1915 // bytes. This will happen when the memory manager thinks that the renderer
1916 // is not visible (which the renderer knows better).
1917 if (allocation
.bytesLimitWhenVisible
) {
1918 ManagedMemoryPolicy
policy(
1919 allocation
.bytesLimitWhenVisible
,
1920 PriorityCutoff(allocation
.priorityCutoffWhenVisible
),
1921 allocation
.bytesLimitWhenNotVisible
,
1922 PriorityCutoff(allocation
.priorityCutoffWhenNotVisible
));
1924 if (allocation
.enforceButDoNotKeepAsPolicy
)
1925 client_
->EnforceManagedMemoryPolicy(policy
);
1927 client_
->SetManagedMemoryPolicy(policy
);
1930 bool old_discard_backbuffer_when_not_visible
=
1931 discard_backbuffer_when_not_visible_
;
1932 discard_backbuffer_when_not_visible_
= !allocation
.suggestHaveBackbuffer
;
1933 EnforceMemoryPolicy();
1934 if (allocation
.enforceButDoNotKeepAsPolicy
)
1935 discard_backbuffer_when_not_visible_
=
1936 old_discard_backbuffer_when_not_visible
;
1939 ManagedMemoryPolicy::PriorityCutoff
GLRenderer::PriorityCutoff(
1940 WebKit::WebGraphicsMemoryAllocation::PriorityCutoff priority_cutoff
) {
1941 // This is simple a 1:1 map, the names differ only because the WebKit names
1942 // should be to match the cc names.
1943 switch (priority_cutoff
) {
1944 case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowNothing
:
1945 return ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING
;
1946 case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleOnly
:
1947 return ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY
;
1948 case WebKit::WebGraphicsMemoryAllocation::
1949 PriorityCutoffAllowVisibleAndNearby
:
1950 return ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE
;
1951 case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowEverything
:
1952 return ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING
;
1955 return ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING
;
1958 void GLRenderer::EnforceMemoryPolicy() {
1960 TRACE_EVENT0("cc", "GLRenderer::EnforceMemoryPolicy dropping resources");
1961 ReleaseRenderPassTextures();
1962 if (discard_backbuffer_when_not_visible_
)
1963 DiscardBackbuffer();
1964 resource_provider_
->ReleaseCachedData();
1965 GLC(context_
, context_
->flush());
1969 void GLRenderer::DiscardBackbuffer() {
1970 if (is_backbuffer_discarded_
)
1973 output_surface_
->DiscardBackbuffer();
1975 is_backbuffer_discarded_
= true;
1977 // Damage tracker needs a full reset every time framebuffer is discarded.
1978 client_
->SetFullRootLayerDamage();
1981 void GLRenderer::EnsureBackbuffer() {
1982 if (!is_backbuffer_discarded_
)
1985 output_surface_
->EnsureBackbuffer();
1986 is_backbuffer_discarded_
= false;
1989 void GLRenderer::GetFramebufferPixels(void* pixels
, gfx::Rect rect
) {
1990 DCHECK(rect
.right() <= ViewportWidth());
1991 DCHECK(rect
.bottom() <= ViewportHeight());
1996 MakeContextCurrent();
1998 bool do_workaround
= NeedsIOSurfaceReadbackWorkaround();
2000 GLuint temporary_texture
= 0;
2001 GLuint temporary_fbo
= 0;
2003 if (do_workaround
) {
2004 // On Mac OS X, calling glReadPixels() against an FBO whose color attachment
2005 // is an IOSurface-backed texture causes corruption of future glReadPixels()
2006 // calls, even those on different OpenGL contexts. It is believed that this
2007 // is the root cause of top crasher
2008 // http://crbug.com/99393. <rdar://problem/10949687>
2010 temporary_texture
= context_
->createTexture();
2011 GLC(context_
, context_
->bindTexture(GL_TEXTURE_2D
, temporary_texture
));
2013 context_
->texParameteri(
2014 GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
));
2016 context_
->texParameteri(
2017 GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
));
2019 context_
->texParameteri(
2020 GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
));
2022 context_
->texParameteri(
2023 GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
));
2024 // Copy the contents of the current (IOSurface-backed) framebuffer into a
2025 // temporary texture.
2027 context_
->copyTexImage2D(GL_TEXTURE_2D
,
2032 ViewportSize().width(),
2033 ViewportSize().height(),
2035 temporary_fbo
= context_
->createFramebuffer();
2036 // Attach this texture to an FBO, and perform the readback from that FBO.
2037 GLC(context_
, context_
->bindFramebuffer(GL_FRAMEBUFFER
, temporary_fbo
));
2039 context_
->framebufferTexture2D(GL_FRAMEBUFFER
,
2040 GL_COLOR_ATTACHMENT0
,
2045 DCHECK(context_
->checkFramebufferStatus(GL_FRAMEBUFFER
) ==
2046 GL_FRAMEBUFFER_COMPLETE
);
2049 scoped_ptr
<uint8_t[]> src_pixels(
2050 new uint8_t[rect
.width() * rect
.height() * 4]);
2052 context_
->readPixels(rect
.x(),
2053 ViewportSize().height() - rect
.bottom(),
2060 uint8_t* dest_pixels
= static_cast<uint8_t*>(pixels
);
2061 size_t row_bytes
= rect
.width() * 4;
2062 int num_rows
= rect
.height();
2063 size_t total_bytes
= num_rows
* row_bytes
;
2064 for (size_t dest_y
= 0; dest_y
< total_bytes
; dest_y
+= row_bytes
) {
2066 size_t src_y
= total_bytes
- dest_y
- row_bytes
;
2067 // Swizzle BGRA -> RGBA.
2068 for (size_t x
= 0; x
< row_bytes
; x
+= 4) {
2069 dest_pixels
[dest_y
+ (x
+ 0)] = src_pixels
.get()[src_y
+ (x
+ 2)];
2070 dest_pixels
[dest_y
+ (x
+ 1)] = src_pixels
.get()[src_y
+ (x
+ 1)];
2071 dest_pixels
[dest_y
+ (x
+ 2)] = src_pixels
.get()[src_y
+ (x
+ 0)];
2072 dest_pixels
[dest_y
+ (x
+ 3)] = src_pixels
.get()[src_y
+ (x
+ 3)];
2076 if (do_workaround
) {
2078 GLC(context_
, context_
->bindFramebuffer(GL_FRAMEBUFFER
, 0));
2079 GLC(context_
, context_
->bindTexture(GL_TEXTURE_2D
, 0));
2080 GLC(context_
, context_
->deleteFramebuffer(temporary_fbo
));
2081 GLC(context_
, context_
->deleteTexture(temporary_texture
));
2084 EnforceMemoryPolicy();
2087 bool GLRenderer::GetFramebufferTexture(ScopedResource
* texture
,
2088 gfx::Rect device_rect
) {
2089 DCHECK(!texture
->id() || (texture
->size() == device_rect
.size() &&
2090 texture
->format() == GL_RGB
));
2092 if (!texture
->id() && !texture
->Allocate(device_rect
.size(),
2094 ResourceProvider::TextureUsageAny
))
2097 ResourceProvider::ScopedWriteLockGL
lock(resource_provider_
, texture
->id());
2098 GLC(context_
, context_
->bindTexture(GL_TEXTURE_2D
, lock
.texture_id()));
2100 context_
->copyTexImage2D(GL_TEXTURE_2D
,
2105 device_rect
.width(),
2106 device_rect
.height(),
2111 bool GLRenderer::UseScopedTexture(DrawingFrame
* frame
,
2112 const ScopedResource
* texture
,
2113 gfx::Rect viewport_rect
) {
2114 DCHECK(texture
->id());
2115 frame
->current_render_pass
= NULL
;
2116 frame
->current_texture
= texture
;
2118 return BindFramebufferToTexture(frame
, texture
, viewport_rect
);
2121 void GLRenderer::BindFramebufferToOutputSurface(DrawingFrame
* frame
) {
2122 current_framebuffer_lock_
.reset();
2123 output_surface_
->BindFramebuffer();
2126 bool GLRenderer::BindFramebufferToTexture(DrawingFrame
* frame
,
2127 const ScopedResource
* texture
,
2128 gfx::Rect framebuffer_rect
) {
2129 DCHECK(texture
->id());
2132 context_
->bindFramebuffer(GL_FRAMEBUFFER
, offscreen_framebuffer_id_
));
2133 current_framebuffer_lock_
=
2134 make_scoped_ptr(new ResourceProvider::ScopedWriteLockGL(
2135 resource_provider_
, texture
->id()));
2136 unsigned texture_id
= current_framebuffer_lock_
->texture_id();
2138 context_
->framebufferTexture2D(
2139 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, GL_TEXTURE_2D
, texture_id
, 0));
2141 DCHECK(context_
->checkFramebufferStatus(GL_FRAMEBUFFER
) ==
2142 GL_FRAMEBUFFER_COMPLETE
|| IsContextLost());
2144 InitializeMatrices(frame
, framebuffer_rect
, false);
2145 SetDrawViewportSize(framebuffer_rect
.size());
2150 void GLRenderer::SetScissorTestRect(gfx::Rect scissor_rect
) {
2151 EnsureScissorTestEnabled();
2153 // Don't unnecessarily ask the context to change the scissor, because it
2154 // may cause undesired GPU pipeline flushes.
2155 if (scissor_rect
== scissor_rect_
)
2158 scissor_rect_
= scissor_rect
;
2159 FlushTextureQuadCache();
2161 context_
->scissor(scissor_rect
.x(),
2163 scissor_rect
.width(),
2164 scissor_rect
.height()));
2167 void GLRenderer::SetDrawViewportSize(gfx::Size viewport_size
) {
2169 context_
->viewport(0, 0, viewport_size
.width(), viewport_size
.height()));
2172 bool GLRenderer::MakeContextCurrent() { return context_
->makeContextCurrent(); }
2174 bool GLRenderer::InitializeSharedObjects() {
2175 TRACE_EVENT0("cc", "GLRenderer::InitializeSharedObjects");
2176 MakeContextCurrent();
2178 // Create an FBO for doing offscreen rendering.
2179 GLC(context_
, offscreen_framebuffer_id_
= context_
->createFramebuffer());
2181 // We will always need these programs to render, so create the programs
2182 // eagerly so that the shader compilation can start while we do other work.
2183 // Other programs are created lazily on first access.
2184 shared_geometry_
= make_scoped_ptr(
2185 new GeometryBinding(context_
, QuadVertexRect()));
2186 render_pass_program_
= make_scoped_ptr(
2187 new RenderPassProgram(context_
, TexCoordPrecisionMedium
));
2188 render_pass_program_highp_
= make_scoped_ptr(
2189 new RenderPassProgram(context_
, TexCoordPrecisionHigh
));
2190 tile_program_
= make_scoped_ptr(
2191 new TileProgram(context_
, TexCoordPrecisionMedium
));
2192 tile_program_opaque_
= make_scoped_ptr(
2193 new TileProgramOpaque(context_
, TexCoordPrecisionMedium
));
2194 tile_program_highp_
= make_scoped_ptr(
2195 new TileProgram(context_
, TexCoordPrecisionHigh
));
2196 tile_program_opaque_highp_
= make_scoped_ptr(
2197 new TileProgramOpaque(context_
, TexCoordPrecisionHigh
));
2199 GLC(context_
, context_
->flush());
2204 const GLRenderer::TileCheckerboardProgram
*
2205 GLRenderer::GetTileCheckerboardProgram() {
2206 if (!tile_checkerboard_program_
)
2207 tile_checkerboard_program_
= make_scoped_ptr(
2208 new TileCheckerboardProgram(context_
, TexCoordPrecisionNA
));
2209 if (!tile_checkerboard_program_
->initialized()) {
2210 TRACE_EVENT0("cc", "GLRenderer::checkerboardProgram::initalize");
2211 tile_checkerboard_program_
->Initialize(context_
, is_using_bind_uniform_
);
2213 return tile_checkerboard_program_
.get();
2216 const GLRenderer::DebugBorderProgram
* GLRenderer::GetDebugBorderProgram() {
2217 if (!debug_border_program_
)
2218 debug_border_program_
= make_scoped_ptr(
2219 new DebugBorderProgram(context_
, TexCoordPrecisionNA
));
2220 if (!debug_border_program_
->initialized()) {
2221 TRACE_EVENT0("cc", "GLRenderer::debugBorderProgram::initialize");
2222 debug_border_program_
->Initialize(context_
, is_using_bind_uniform_
);
2224 return debug_border_program_
.get();
2227 const GLRenderer::SolidColorProgram
* GLRenderer::GetSolidColorProgram() {
2228 if (!solid_color_program_
)
2229 solid_color_program_
= make_scoped_ptr(
2230 new SolidColorProgram(context_
, TexCoordPrecisionNA
));
2231 if (!solid_color_program_
->initialized()) {
2232 TRACE_EVENT0("cc", "GLRenderer::solidColorProgram::initialize");
2233 solid_color_program_
->Initialize(context_
, is_using_bind_uniform_
);
2235 return solid_color_program_
.get();
2238 const GLRenderer::SolidColorProgramAA
* GLRenderer::GetSolidColorProgramAA() {
2239 if (!solid_color_program_aa_
) {
2240 solid_color_program_aa_
=
2241 make_scoped_ptr(new SolidColorProgramAA(context_
, TexCoordPrecisionNA
));
2243 if (!solid_color_program_aa_
->initialized()) {
2244 TRACE_EVENT0("cc", "GLRenderer::solidColorProgramAA::initialize");
2245 solid_color_program_aa_
->Initialize(context_
, is_using_bind_uniform_
);
2247 return solid_color_program_aa_
.get();
2250 const GLRenderer::RenderPassProgram
* GLRenderer::GetRenderPassProgram(
2251 TexCoordPrecision precision
) {
2252 scoped_ptr
<RenderPassProgram
>& program
=
2253 (precision
== TexCoordPrecisionHigh
) ? render_pass_program_highp_
2254 : render_pass_program_
;
2256 if (!program
->initialized()) {
2257 TRACE_EVENT0("cc", "GLRenderer::renderPassProgram::initialize");
2258 program
->Initialize(context_
, is_using_bind_uniform_
);
2260 return program
.get();
2263 const GLRenderer::RenderPassProgramAA
* GLRenderer::GetRenderPassProgramAA(
2264 TexCoordPrecision precision
) {
2265 scoped_ptr
<RenderPassProgramAA
>& program
=
2266 (precision
== TexCoordPrecisionHigh
) ? render_pass_program_aa_highp_
2267 : render_pass_program_aa_
;
2270 make_scoped_ptr(new RenderPassProgramAA(context_
, precision
));
2271 if (!program
->initialized()) {
2272 TRACE_EVENT0("cc", "GLRenderer::renderPassProgramAA::initialize");
2273 program
->Initialize(context_
, is_using_bind_uniform_
);
2275 return program
.get();
2278 const GLRenderer::RenderPassMaskProgram
*
2279 GLRenderer::GetRenderPassMaskProgram(TexCoordPrecision precision
) {
2280 scoped_ptr
<RenderPassMaskProgram
>& program
=
2281 (precision
== TexCoordPrecisionHigh
) ? render_pass_mask_program_highp_
2282 : render_pass_mask_program_
;
2284 program
= make_scoped_ptr(new RenderPassMaskProgram(context_
, precision
));
2285 if (!program
->initialized()) {
2286 TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize");
2287 program
->Initialize(context_
, is_using_bind_uniform_
);
2289 return program
.get();
2292 const GLRenderer::RenderPassMaskProgramAA
*
2293 GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision
) {
2294 scoped_ptr
<RenderPassMaskProgramAA
>& program
=
2295 (precision
== TexCoordPrecisionHigh
) ? render_pass_mask_program_aa_highp_
2296 : render_pass_mask_program_aa_
;
2299 make_scoped_ptr(new RenderPassMaskProgramAA(context_
, precision
));
2300 if (!program
->initialized()) {
2301 TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize");
2302 program
->Initialize(context_
, is_using_bind_uniform_
);
2304 return program
.get();
2307 const GLRenderer::RenderPassColorMatrixProgram
*
2308 GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision
) {
2309 scoped_ptr
<RenderPassColorMatrixProgram
>& program
=
2310 (precision
== TexCoordPrecisionHigh
) ?
2311 render_pass_color_matrix_program_highp_
:
2312 render_pass_color_matrix_program_
;
2314 program
= make_scoped_ptr(
2315 new RenderPassColorMatrixProgram(context_
, precision
));
2316 if (!program
->initialized()) {
2317 TRACE_EVENT0("cc", "GLRenderer::renderPassColorMatrixProgram::initialize");
2318 program
->Initialize(context_
, is_using_bind_uniform_
);
2320 return program
.get();
2323 const GLRenderer::RenderPassColorMatrixProgramAA
*
2324 GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision
) {
2325 scoped_ptr
<RenderPassColorMatrixProgramAA
>& program
=
2326 (precision
== TexCoordPrecisionHigh
) ?
2327 render_pass_color_matrix_program_aa_highp_
:
2328 render_pass_color_matrix_program_aa_
;
2330 program
= make_scoped_ptr(
2331 new RenderPassColorMatrixProgramAA(context_
, precision
));
2332 if (!program
->initialized()) {
2334 "GLRenderer::renderPassColorMatrixProgramAA::initialize");
2335 program
->Initialize(context_
, is_using_bind_uniform_
);
2337 return program
.get();
2340 const GLRenderer::RenderPassMaskColorMatrixProgram
*
2341 GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision
) {
2342 scoped_ptr
<RenderPassMaskColorMatrixProgram
>& program
=
2343 (precision
== TexCoordPrecisionHigh
) ?
2344 render_pass_mask_color_matrix_program_highp_
:
2345 render_pass_mask_color_matrix_program_
;
2347 program
= make_scoped_ptr(
2348 new RenderPassMaskColorMatrixProgram(context_
, precision
));
2349 if (!program
->initialized()) {
2351 "GLRenderer::renderPassMaskColorMatrixProgram::initialize");
2352 program
->Initialize(context_
, is_using_bind_uniform_
);
2354 return program
.get();
2357 const GLRenderer::RenderPassMaskColorMatrixProgramAA
*
2358 GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision
) {
2359 scoped_ptr
<RenderPassMaskColorMatrixProgramAA
>& program
=
2360 (precision
== TexCoordPrecisionHigh
) ?
2361 render_pass_mask_color_matrix_program_aa_highp_
:
2362 render_pass_mask_color_matrix_program_aa_
;
2364 program
= make_scoped_ptr(
2365 new RenderPassMaskColorMatrixProgramAA(context_
, precision
));
2366 if (!program
->initialized()) {
2368 "GLRenderer::renderPassMaskColorMatrixProgramAA::initialize");
2369 program
->Initialize(context_
, is_using_bind_uniform_
);
2371 return program
.get();
2374 const GLRenderer::TileProgram
* GLRenderer::GetTileProgram(
2375 TexCoordPrecision precision
) {
2376 scoped_ptr
<TileProgram
>& program
=
2377 (precision
== TexCoordPrecisionHigh
) ? tile_program_highp_
2380 if (!program
->initialized()) {
2381 TRACE_EVENT0("cc", "GLRenderer::tileProgram::initialize");
2382 program
->Initialize(context_
, is_using_bind_uniform_
);
2384 return program
.get();
2387 const GLRenderer::TileProgramOpaque
* GLRenderer::GetTileProgramOpaque(
2388 TexCoordPrecision precision
) {
2389 scoped_ptr
<TileProgramOpaque
>& program
=
2390 (precision
== TexCoordPrecisionHigh
) ? tile_program_opaque_highp_
2391 : tile_program_opaque_
;
2393 if (!program
->initialized()) {
2394 TRACE_EVENT0("cc", "GLRenderer::tileProgramOpaque::initialize");
2395 program
->Initialize(context_
, is_using_bind_uniform_
);
2397 return program
.get();
2400 const GLRenderer::TileProgramAA
* GLRenderer::GetTileProgramAA(
2401 TexCoordPrecision precision
) {
2402 scoped_ptr
<TileProgramAA
>& program
=
2403 (precision
== TexCoordPrecisionHigh
) ? tile_program_aa_highp_
2406 program
= make_scoped_ptr(new TileProgramAA(context_
, precision
));
2407 if (!program
->initialized()) {
2408 TRACE_EVENT0("cc", "GLRenderer::tileProgramAA::initialize");
2409 program
->Initialize(context_
, is_using_bind_uniform_
);
2411 return program
.get();
2414 const GLRenderer::TileProgramSwizzle
* GLRenderer::GetTileProgramSwizzle(
2415 TexCoordPrecision precision
) {
2416 scoped_ptr
<TileProgramSwizzle
>& program
=
2417 (precision
== TexCoordPrecisionHigh
) ? tile_program_swizzle_highp_
2418 : tile_program_swizzle_
;
2420 program
= make_scoped_ptr(new TileProgramSwizzle(context_
, precision
));
2421 if (!program
->initialized()) {
2422 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzle::initialize");
2423 program
->Initialize(context_
, is_using_bind_uniform_
);
2425 return program
.get();
2428 const GLRenderer::TileProgramSwizzleOpaque
*
2429 GLRenderer::GetTileProgramSwizzleOpaque(TexCoordPrecision precision
) {
2430 scoped_ptr
<TileProgramSwizzleOpaque
>& program
=
2431 (precision
== TexCoordPrecisionHigh
) ? tile_program_swizzle_opaque_highp_
2432 : tile_program_swizzle_opaque_
;
2434 program
= make_scoped_ptr(
2435 new TileProgramSwizzleOpaque(context_
, precision
));
2436 if (!program
->initialized()) {
2437 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleOpaque::initialize");
2438 program
->Initialize(context_
, is_using_bind_uniform_
);
2440 return program
.get();
2443 const GLRenderer::TileProgramSwizzleAA
* GLRenderer::GetTileProgramSwizzleAA(
2444 TexCoordPrecision precision
) {
2445 scoped_ptr
<TileProgramSwizzleAA
>& program
=
2446 (precision
== TexCoordPrecisionHigh
) ? tile_program_swizzle_aa_highp_
2447 : tile_program_swizzle_aa_
;
2449 program
= make_scoped_ptr(new TileProgramSwizzleAA(context_
, precision
));
2450 if (!program
->initialized()) {
2451 TRACE_EVENT0("cc", "GLRenderer::tileProgramSwizzleAA::initialize");
2452 program
->Initialize(context_
, is_using_bind_uniform_
);
2454 return program
.get();
2457 const GLRenderer::TextureProgram
* GLRenderer::GetTextureProgram(
2458 TexCoordPrecision precision
) {
2459 scoped_ptr
<TextureProgram
>& program
=
2460 (precision
== TexCoordPrecisionHigh
) ? texture_program_highp_
2463 program
= make_scoped_ptr(new TextureProgram(context_
, precision
));
2464 if (!program
->initialized()) {
2465 TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize");
2466 program
->Initialize(context_
, is_using_bind_uniform_
);
2468 return program
.get();
2471 const GLRenderer::TextureProgramFlip
* GLRenderer::GetTextureProgramFlip(
2472 TexCoordPrecision precision
) {
2473 scoped_ptr
<TextureProgramFlip
>& program
=
2474 (precision
== TexCoordPrecisionHigh
) ? texture_program_flip_highp_
2475 : texture_program_flip_
;
2477 program
= make_scoped_ptr(new TextureProgramFlip(context_
, precision
));
2478 if (!program
->initialized()) {
2479 TRACE_EVENT0("cc", "GLRenderer::textureProgramFlip::initialize");
2480 program
->Initialize(context_
, is_using_bind_uniform_
);
2482 return program
.get();
2485 const GLRenderer::TextureIOSurfaceProgram
*
2486 GLRenderer::GetTextureIOSurfaceProgram(TexCoordPrecision precision
) {
2487 scoped_ptr
<TextureIOSurfaceProgram
>& program
=
2488 (precision
== TexCoordPrecisionHigh
) ? texture_io_surface_program_highp_
2489 : texture_io_surface_program_
;
2492 make_scoped_ptr(new TextureIOSurfaceProgram(context_
, precision
));
2493 if (!program
->initialized()) {
2494 TRACE_EVENT0("cc", "GLRenderer::textureIOSurfaceProgram::initialize");
2495 program
->Initialize(context_
, is_using_bind_uniform_
);
2497 return program
.get();
2500 const GLRenderer::VideoYUVProgram
* GLRenderer::GetVideoYUVProgram(
2501 TexCoordPrecision precision
) {
2502 scoped_ptr
<VideoYUVProgram
>& program
=
2503 (precision
== TexCoordPrecisionHigh
) ? video_yuv_program_highp_
2504 : video_yuv_program_
;
2506 program
= make_scoped_ptr(new VideoYUVProgram(context_
, precision
));
2507 if (!program
->initialized()) {
2508 TRACE_EVENT0("cc", "GLRenderer::videoYUVProgram::initialize");
2509 program
->Initialize(context_
, is_using_bind_uniform_
);
2511 return program
.get();
2514 const GLRenderer::VideoStreamTextureProgram
*
2515 GLRenderer::GetVideoStreamTextureProgram(TexCoordPrecision precision
) {
2516 if (!Capabilities().using_egl_image
)
2518 scoped_ptr
<VideoStreamTextureProgram
>& program
=
2519 (precision
== TexCoordPrecisionHigh
) ? video_stream_texture_program_highp_
2520 : video_stream_texture_program_
;
2523 make_scoped_ptr(new VideoStreamTextureProgram(context_
, precision
));
2524 if (!program
->initialized()) {
2525 TRACE_EVENT0("cc", "GLRenderer::streamTextureProgram::initialize");
2526 program
->Initialize(context_
, is_using_bind_uniform_
);
2528 return program
.get();
2531 void GLRenderer::CleanupSharedObjects() {
2532 MakeContextCurrent();
2534 shared_geometry_
.reset();
2537 tile_program_
->Cleanup(context_
);
2538 if (tile_program_opaque_
)
2539 tile_program_opaque_
->Cleanup(context_
);
2540 if (tile_program_swizzle_
)
2541 tile_program_swizzle_
->Cleanup(context_
);
2542 if (tile_program_swizzle_opaque_
)
2543 tile_program_swizzle_opaque_
->Cleanup(context_
);
2544 if (tile_program_aa_
)
2545 tile_program_aa_
->Cleanup(context_
);
2546 if (tile_program_swizzle_aa_
)
2547 tile_program_swizzle_aa_
->Cleanup(context_
);
2548 if (tile_checkerboard_program_
)
2549 tile_checkerboard_program_
->Cleanup(context_
);
2551 if (tile_program_highp_
)
2552 tile_program_highp_
->Cleanup(context_
);
2553 if (tile_program_opaque_highp_
)
2554 tile_program_opaque_highp_
->Cleanup(context_
);
2555 if (tile_program_swizzle_highp_
)
2556 tile_program_swizzle_highp_
->Cleanup(context_
);
2557 if (tile_program_swizzle_opaque_highp_
)
2558 tile_program_swizzle_opaque_highp_
->Cleanup(context_
);
2559 if (tile_program_aa_highp_
)
2560 tile_program_aa_highp_
->Cleanup(context_
);
2561 if (tile_program_swizzle_aa_highp_
)
2562 tile_program_swizzle_aa_highp_
->Cleanup(context_
);
2564 if (render_pass_mask_program_
)
2565 render_pass_mask_program_
->Cleanup(context_
);
2566 if (render_pass_program_
)
2567 render_pass_program_
->Cleanup(context_
);
2568 if (render_pass_mask_program_aa_
)
2569 render_pass_mask_program_aa_
->Cleanup(context_
);
2570 if (render_pass_program_aa_
)
2571 render_pass_program_aa_
->Cleanup(context_
);
2572 if (render_pass_color_matrix_program_
)
2573 render_pass_color_matrix_program_
->Cleanup(context_
);
2574 if (render_pass_mask_color_matrix_program_aa_
)
2575 render_pass_mask_color_matrix_program_aa_
->Cleanup(context_
);
2576 if (render_pass_color_matrix_program_aa_
)
2577 render_pass_color_matrix_program_aa_
->Cleanup(context_
);
2578 if (render_pass_mask_color_matrix_program_
)
2579 render_pass_mask_color_matrix_program_
->Cleanup(context_
);
2581 if (render_pass_mask_program_highp_
)
2582 render_pass_mask_program_highp_
->Cleanup(context_
);
2583 if (render_pass_program_highp_
)
2584 render_pass_program_highp_
->Cleanup(context_
);
2585 if (render_pass_mask_program_aa_highp_
)
2586 render_pass_mask_program_aa_highp_
->Cleanup(context_
);
2587 if (render_pass_program_aa_highp_
)
2588 render_pass_program_aa_highp_
->Cleanup(context_
);
2589 if (render_pass_color_matrix_program_highp_
)
2590 render_pass_color_matrix_program_highp_
->Cleanup(context_
);
2591 if (render_pass_mask_color_matrix_program_aa_highp_
)
2592 render_pass_mask_color_matrix_program_aa_highp_
->Cleanup(context_
);
2593 if (render_pass_color_matrix_program_aa_highp_
)
2594 render_pass_color_matrix_program_aa_highp_
->Cleanup(context_
);
2595 if (render_pass_mask_color_matrix_program_highp_
)
2596 render_pass_mask_color_matrix_program_highp_
->Cleanup(context_
);
2598 if (texture_program_
)
2599 texture_program_
->Cleanup(context_
);
2600 if (texture_program_flip_
)
2601 texture_program_flip_
->Cleanup(context_
);
2602 if (texture_io_surface_program_
)
2603 texture_io_surface_program_
->Cleanup(context_
);
2605 if (texture_program_highp_
)
2606 texture_program_highp_
->Cleanup(context_
);
2607 if (texture_program_flip_highp_
)
2608 texture_program_flip_highp_
->Cleanup(context_
);
2609 if (texture_io_surface_program_highp_
)
2610 texture_io_surface_program_highp_
->Cleanup(context_
);
2612 if (video_yuv_program_
)
2613 video_yuv_program_
->Cleanup(context_
);
2614 if (video_stream_texture_program_
)
2615 video_stream_texture_program_
->Cleanup(context_
);
2617 if (video_yuv_program_highp_
)
2618 video_yuv_program_highp_
->Cleanup(context_
);
2619 if (video_stream_texture_program_highp_
)
2620 video_stream_texture_program_highp_
->Cleanup(context_
);
2622 if (debug_border_program_
)
2623 debug_border_program_
->Cleanup(context_
);
2624 if (solid_color_program_
)
2625 solid_color_program_
->Cleanup(context_
);
2626 if (solid_color_program_aa_
)
2627 solid_color_program_aa_
->Cleanup(context_
);
2629 if (offscreen_framebuffer_id_
)
2630 GLC(context_
, context_
->deleteFramebuffer(offscreen_framebuffer_id_
));
2632 if (on_demand_tile_raster_resource_id_
)
2633 resource_provider_
->DeleteResource(on_demand_tile_raster_resource_id_
);
2635 ReleaseRenderPassTextures();
2638 bool GLRenderer::IsContextLost() {
2639 return (context_
->getGraphicsResetStatusARB() != GL_NO_ERROR
);