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