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