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