OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * |
| 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are |
| 6 * met: |
| 7 * |
| 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the |
| 13 * distribution. |
| 14 * * Neither the name of Google Inc. nor the names of its |
| 15 * contributors may be used to endorse or promote products derived from |
| 16 * this software without specific prior written permission. |
| 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ |
| 30 |
| 31 |
| 32 #include "config.h" |
| 33 |
| 34 #if USE(ACCELERATED_COMPOSITING) |
| 35 #include "LayerRendererChromium.h" |
| 36 |
| 37 #include "Extensions3D.h" |
| 38 #include "FloatQuad.h" |
| 39 #include "GeometryBinding.h" |
| 40 #include "GrTexture.h" |
| 41 #include "ManagedTexture.h" |
| 42 #include "NotImplemented.h" |
| 43 #include "PlatformColor.h" |
| 44 //#include "SharedGraphicsContext3D.h" |
| 45 #include "SkBitmap.h" |
| 46 #include "SkColor.h" |
| 47 #include "TextureManager.h" |
| 48 #include "ThrottledTextureUploader.h" |
| 49 #include "TraceEvent.h" |
| 50 #include "TrackingTextureAllocator.h" |
| 51 #include "cc/CCCheckerboardDrawQuad.h" |
| 52 #include "cc/CCDebugBorderDrawQuad.h" |
| 53 #include "cc/CCIOSurfaceDrawQuad.h" |
| 54 #include "cc/CCLayerQuad.h" |
| 55 #include "cc/CCMathUtil.h" |
| 56 #include "cc/CCProxy.h" |
| 57 #include "cc/CCRenderPass.h" |
| 58 #include "cc/CCRenderPassDrawQuad.h" |
| 59 #include "cc/CCRenderSurfaceFilters.h" |
| 60 #include "cc/CCSettings.h" |
| 61 #include "cc/CCSingleThreadProxy.h" |
| 62 #include "cc/CCSolidColorDrawQuad.h" |
| 63 #include "cc/CCStreamVideoDrawQuad.h" |
| 64 #include "cc/CCTextureDrawQuad.h" |
| 65 #include "cc/CCTileDrawQuad.h" |
| 66 #include "cc/CCVideoLayerImpl.h" |
| 67 #include "cc/CCYUVVideoDrawQuad.h" |
| 68 #include <public/WebGraphicsContext3D.h> |
| 69 #include <public/WebVideoFrame.h> |
| 70 #include <wtf/CurrentTime.h> |
| 71 #include <wtf/MainThread.h> |
| 72 #include <wtf/text/StringHash.h> |
| 73 |
| 74 using namespace std; |
| 75 using WebKit::WebGraphicsContext3D; |
| 76 using WebKit::WebGraphicsMemoryAllocation; |
| 77 using WebKit::WebTransformationMatrix; |
| 78 |
| 79 namespace WebCore { |
| 80 |
| 81 namespace { |
| 82 |
| 83 static WebTransformationMatrix orthoMatrix(float left, float right, float bottom
, float top) |
| 84 { |
| 85 float deltaX = right - left; |
| 86 float deltaY = top - bottom; |
| 87 WebTransformationMatrix ortho; |
| 88 if (!deltaX || !deltaY) |
| 89 return ortho; |
| 90 ortho.setM11(2.0f / deltaX); |
| 91 ortho.setM41(-(right + left) / deltaX); |
| 92 ortho.setM22(2.0f / deltaY); |
| 93 ortho.setM42(-(top + bottom) / deltaY); |
| 94 |
| 95 // Z component of vertices is always set to zero as we don't use the depth b
uffer |
| 96 // while drawing. |
| 97 ortho.setM33(0); |
| 98 |
| 99 return ortho; |
| 100 } |
| 101 |
| 102 static WebTransformationMatrix screenMatrix(int x, int y, int width, int height) |
| 103 { |
| 104 WebTransformationMatrix screen; |
| 105 |
| 106 // Map to viewport. |
| 107 screen.translate3d(x, y, 0); |
| 108 screen.scale3d(width, height, 0); |
| 109 |
| 110 // Map x, y and z to unit square. |
| 111 screen.translate3d(0.5, 0.5, 0.5); |
| 112 screen.scale3d(0.5, 0.5, 0.5); |
| 113 |
| 114 return screen; |
| 115 } |
| 116 |
| 117 bool needsIOSurfaceReadbackWorkaround() |
| 118 { |
| 119 #if OS(DARWIN) |
| 120 return true; |
| 121 #else |
| 122 return false; |
| 123 #endif |
| 124 } |
| 125 |
| 126 class UnthrottledTextureUploader : public TextureUploader { |
| 127 WTF_MAKE_NONCOPYABLE(UnthrottledTextureUploader); |
| 128 public: |
| 129 static PassOwnPtr<UnthrottledTextureUploader> create() |
| 130 { |
| 131 return adoptPtr(new UnthrottledTextureUploader()); |
| 132 } |
| 133 virtual ~UnthrottledTextureUploader() { } |
| 134 |
| 135 virtual bool isBusy() { return false; } |
| 136 virtual void beginUploads() { } |
| 137 virtual void endUploads() { } |
| 138 virtual void uploadTexture(CCGraphicsContext* context, LayerTextureUpdater::
Texture* texture, TextureAllocator* allocator, const IntRect sourceRect, const I
ntRect destRect) { texture->updateRect(context, allocator, sourceRect, destRect)
; } |
| 139 |
| 140 protected: |
| 141 UnthrottledTextureUploader() { } |
| 142 }; |
| 143 |
| 144 } // anonymous namespace |
| 145 |
| 146 PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(CCRendererClient
* client, WebGraphicsContext3D* context, TextureUploaderOption textureUploaderSe
tting) |
| 147 { |
| 148 OwnPtr<LayerRendererChromium> layerRenderer(adoptPtr(new LayerRendererChromi
um(client, context, textureUploaderSetting))); |
| 149 if (!layerRenderer->initialize()) |
| 150 return nullptr; |
| 151 |
| 152 return layerRenderer.release(); |
| 153 } |
| 154 |
| 155 LayerRendererChromium::LayerRendererChromium(CCRendererClient* client, |
| 156 WebGraphicsContext3D* context, |
| 157 TextureUploaderOption textureUpload
erSetting) |
| 158 : CCRenderer(client) |
| 159 , m_currentRenderPass(0) |
| 160 , m_currentManagedTexture(0) |
| 161 , m_offscreenFramebufferId(0) |
| 162 , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f)) |
| 163 , m_context(context) |
| 164 , m_defaultRenderPass(0) |
| 165 , m_isViewportChanged(false) |
| 166 , m_isFramebufferDiscarded(false) |
| 167 , m_visible(true) |
| 168 , m_textureUploaderSetting(textureUploaderSetting) |
| 169 { |
| 170 ASSERT(m_context); |
| 171 } |
| 172 |
| 173 bool LayerRendererChromium::initialize() |
| 174 { |
| 175 if (!m_context->makeContextCurrent()) |
| 176 return false; |
| 177 |
| 178 m_context->setContextLostCallback(this); |
| 179 |
| 180 WebKit::WebString extensionsWebString = m_context->getString(GL_EXTENSIONS); |
| 181 String extensionsString = String(extensionsWebString.data(), extensionsWebSt
ring.length()); |
| 182 Vector<String> extensionsList; |
| 183 extensionsString.split(' ', extensionsList); |
| 184 HashSet<String> extensions; |
| 185 for (size_t i = 0; i < extensionsList.size(); ++i) |
| 186 extensions.add(extensionsList[i]); |
| 187 |
| 188 if (settings().acceleratePainting && extensions.contains("GL_EXT_texture_for
mat_BGRA8888") |
| 189 && extensions.contains("GL_EXT_read_format
_bgra")) |
| 190 m_capabilities.usingAcceleratedPainting = true; |
| 191 else |
| 192 m_capabilities.usingAcceleratedPainting = false; |
| 193 |
| 194 |
| 195 m_capabilities.contextHasCachedFrontBuffer = extensions.contains("GL_CHROMIU
M_front_buffer_cached"); |
| 196 |
| 197 m_capabilities.usingPartialSwap = CCSettings::partialSwapEnabled() && extens
ions.contains("GL_CHROMIUM_post_sub_buffer"); |
| 198 |
| 199 m_capabilities.usingMapSub = extensions.contains("GL_CHROMIUM_map_sub"); |
| 200 |
| 201 // Use the swapBuffers callback only with the threaded proxy. |
| 202 if (CCProxy::hasImplThread()) |
| 203 m_capabilities.usingSwapCompleteCallback = extensions.contains("GL_CHROM
IUM_swapbuffers_complete_callback"); |
| 204 if (m_capabilities.usingSwapCompleteCallback) { |
| 205 m_context->setSwapBuffersCompleteCallbackCHROMIUM(this); |
| 206 } |
| 207 |
| 208 m_capabilities.usingSetVisibility = extensions.contains("GL_CHROMIUM_set_vis
ibility"); |
| 209 |
| 210 if (extensions.contains("GL_CHROMIUM_iosurface")) { |
| 211 ASSERT(extensions.contains("GL_ARB_texture_rectangle")); |
| 212 } |
| 213 |
| 214 m_capabilities.usingTextureUsageHint = extensions.contains("GL_ANGLE_texture
_usage"); |
| 215 |
| 216 m_capabilities.usingTextureStorageExtension = extensions.contains("GL_EXT_te
xture_storage"); |
| 217 |
| 218 m_capabilities.usingGpuMemoryManager = extensions.contains("GL_CHROMIUM_gpu_
memory_manager"); |
| 219 if (m_capabilities.usingGpuMemoryManager) |
| 220 m_context->setMemoryAllocationChangedCallbackCHROMIUM(this); |
| 221 else |
| 222 m_client->setMemoryAllocationLimitBytes(TextureManager::highLimitBytes(v
iewportSize())); |
| 223 |
| 224 m_capabilities.usingDiscardFramebuffer = extensions.contains("GL_CHROMIUM_di
scard_framebuffer"); |
| 225 |
| 226 m_capabilities.usingEglImage = extensions.contains("GL_OES_EGL_image_externa
l"); |
| 227 |
| 228 GLC(m_context, m_context->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_capabilities.m
axTextureSize)); |
| 229 m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_contex
t, extensions.contains("GL_EXT_texture_format_BGRA8888")); |
| 230 |
| 231 if (!initializeSharedObjects()) |
| 232 return false; |
| 233 |
| 234 // Make sure the viewport and context gets initialized, even if it is to zer
o. |
| 235 viewportChanged(); |
| 236 return true; |
| 237 } |
| 238 |
| 239 LayerRendererChromium::~LayerRendererChromium() |
| 240 { |
| 241 ASSERT(CCProxy::isImplThread()); |
| 242 m_context->setSwapBuffersCompleteCallbackCHROMIUM(0); |
| 243 m_context->setMemoryAllocationChangedCallbackCHROMIUM(0); |
| 244 m_context->setContextLostCallback(0); |
| 245 cleanupSharedObjects(); |
| 246 } |
| 247 |
| 248 WebGraphicsContext3D* LayerRendererChromium::context() |
| 249 { |
| 250 return m_context; |
| 251 } |
| 252 |
| 253 void LayerRendererChromium::debugGLCall(WebGraphicsContext3D* context, const cha
r* command, const char* file, int line) |
| 254 { |
| 255 unsigned long error = context->getError(); |
| 256 if (error != GL_NO_ERROR) |
| 257 LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error
%x\n", file, line, command, static_cast<int>(error)); |
| 258 } |
| 259 |
| 260 void LayerRendererChromium::setVisible(bool visible) |
| 261 { |
| 262 if (m_visible == visible) |
| 263 return; |
| 264 m_visible = visible; |
| 265 |
| 266 // TODO: Replace setVisibilityCHROMIUM with an extension to explicitly manag
e front/backbuffers |
| 267 // crbug.com/116049 |
| 268 if (m_capabilities.usingSetVisibility) { |
| 269 m_context->setVisibilityCHROMIUM(visible); |
| 270 } |
| 271 } |
| 272 |
| 273 void LayerRendererChromium::releaseRenderPassTextures() |
| 274 { |
| 275 if (m_implTextureManager) |
| 276 m_implTextureManager->evictAndDeleteAllTextures(m_implTextureAllocator.g
et()); |
| 277 } |
| 278 |
| 279 void LayerRendererChromium::viewportChanged() |
| 280 { |
| 281 m_isViewportChanged = true; |
| 282 |
| 283 // Reset the current RenderPass to force an update of the viewport and |
| 284 // projection matrix next time useRenderPass is called. |
| 285 m_currentRenderPass = 0; |
| 286 } |
| 287 |
| 288 void LayerRendererChromium::clearRenderPass(const CCRenderPass* renderPass, cons
t FloatRect& framebufferDamageRect) |
| 289 { |
| 290 // On DEBUG builds, opaque render passes are cleared to blue to easily see r
egions that were not drawn on the screen. If we |
| 291 // are using partial swap / scissor optimization, then the surface should on
ly |
| 292 // clear the damaged region, so that we don't accidentally clear un-changed
portions |
| 293 // of the screen. |
| 294 |
| 295 if (renderPass->hasTransparentBackground()) |
| 296 GLC(m_context, m_context->clearColor(0, 0, 0, 0)); |
| 297 else |
| 298 GLC(m_context, m_context->clearColor(0, 0, 1, 1)); |
| 299 |
| 300 if (m_capabilities.usingPartialSwap) |
| 301 setScissorToRect(enclosingIntRect(framebufferDamageRect)); |
| 302 else |
| 303 GLC(m_context, m_context->disable(GL_SCISSOR_TEST)); |
| 304 |
| 305 #if defined(NDEBUG) |
| 306 if (renderPass->hasTransparentBackground()) |
| 307 #endif |
| 308 m_context->clear(GL_COLOR_BUFFER_BIT); |
| 309 |
| 310 GLC(m_context, m_context->enable(GL_SCISSOR_TEST)); |
| 311 } |
| 312 |
| 313 |
| 314 void LayerRendererChromium::decideRenderPassAllocationsForFrame(const CCRenderPa
ssList& renderPassesInDrawOrder) |
| 315 { |
| 316 // FIXME: Get this memory limit from GPU Memory Manager |
| 317 size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUse
Bytes(); |
| 318 size_t maxLimitBytes = TextureManager::highLimitBytes(viewportSize()); |
| 319 size_t memoryLimitBytes = maxLimitBytes - contentsMemoryUseBytes > 0u ? maxL
imitBytes - contentsMemoryUseBytes : 0u; |
| 320 |
| 321 m_implTextureManager->setMaxMemoryLimitBytes(memoryLimitBytes); |
| 322 } |
| 323 |
| 324 void LayerRendererChromium::beginDrawingFrame(const CCRenderPass* rootRenderPass
) |
| 325 { |
| 326 // FIXME: Remove this once framebuffer is automatically recreated on first u
se |
| 327 ensureFramebuffer(); |
| 328 |
| 329 m_defaultRenderPass = rootRenderPass; |
| 330 ASSERT(m_defaultRenderPass); |
| 331 |
| 332 if (viewportSize().isEmpty()) |
| 333 return; |
| 334 |
| 335 TRACE_EVENT0("cc", "LayerRendererChromium::drawLayers"); |
| 336 if (m_isViewportChanged) { |
| 337 // Only reshape when we know we are going to draw. Otherwise, the reshap
e |
| 338 // can leave the window at the wrong size if we never draw and the prope
r |
| 339 // viewport size is never set. |
| 340 m_isViewportChanged = false; |
| 341 m_context->reshape(viewportWidth(), viewportHeight()); |
| 342 } |
| 343 |
| 344 makeContextCurrent(); |
| 345 // Bind the common vertex attributes used for drawing all the layers. |
| 346 m_sharedGeometry->prepareForDraw(); |
| 347 |
| 348 GLC(m_context, m_context->disable(GL_DEPTH_TEST)); |
| 349 GLC(m_context, m_context->disable(GL_CULL_FACE)); |
| 350 GLC(m_context, m_context->colorMask(true, true, true, true)); |
| 351 GLC(m_context, m_context->enable(GL_BLEND)); |
| 352 GLC(m_context, m_context->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); |
| 353 } |
| 354 |
| 355 void LayerRendererChromium::doNoOp() |
| 356 { |
| 357 GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0)); |
| 358 GLC(m_context, m_context->flush()); |
| 359 } |
| 360 |
| 361 void LayerRendererChromium::drawRenderPass(const CCRenderPass* renderPass, const
FloatRect& framebufferDamageRect) |
| 362 { |
| 363 if (!useRenderPass(renderPass)) |
| 364 return; |
| 365 |
| 366 clearRenderPass(renderPass, framebufferDamageRect); |
| 367 |
| 368 const CCQuadList& quadList = renderPass->quadList(); |
| 369 for (CCQuadList::constBackToFrontIterator it = quadList.backToFrontBegin();
it != quadList.backToFrontEnd(); ++it) |
| 370 drawQuad(it->get()); |
| 371 } |
| 372 |
| 373 void LayerRendererChromium::drawQuad(const CCDrawQuad* quad) |
| 374 { |
| 375 IntRect scissorRect = quad->scissorRect(); |
| 376 |
| 377 ASSERT(!scissorRect.isEmpty()); |
| 378 if (scissorRect.isEmpty()) |
| 379 return; |
| 380 |
| 381 setScissorToRect(scissorRect); |
| 382 |
| 383 if (quad->needsBlending()) |
| 384 GLC(m_context, m_context->enable(GL_BLEND)); |
| 385 else |
| 386 GLC(m_context, m_context->disable(GL_BLEND)); |
| 387 |
| 388 switch (quad->material()) { |
| 389 case CCDrawQuad::Invalid: |
| 390 ASSERT_NOT_REACHED(); |
| 391 break; |
| 392 case CCDrawQuad::Checkerboard: |
| 393 drawCheckerboardQuad(quad->toCheckerboardDrawQuad()); |
| 394 break; |
| 395 case CCDrawQuad::DebugBorder: |
| 396 drawDebugBorderQuad(quad->toDebugBorderDrawQuad()); |
| 397 break; |
| 398 case CCDrawQuad::IOSurfaceContent: |
| 399 drawIOSurfaceQuad(quad->toIOSurfaceDrawQuad()); |
| 400 break; |
| 401 case CCDrawQuad::RenderPass: |
| 402 drawRenderPassQuad(quad->toRenderPassDrawQuad()); |
| 403 break; |
| 404 case CCDrawQuad::SolidColor: |
| 405 drawSolidColorQuad(quad->toSolidColorDrawQuad()); |
| 406 break; |
| 407 case CCDrawQuad::StreamVideoContent: |
| 408 drawStreamVideoQuad(quad->toStreamVideoDrawQuad()); |
| 409 break; |
| 410 case CCDrawQuad::TextureContent: |
| 411 drawTextureQuad(quad->toTextureDrawQuad()); |
| 412 break; |
| 413 case CCDrawQuad::TiledContent: |
| 414 drawTileQuad(quad->toTileDrawQuad()); |
| 415 break; |
| 416 case CCDrawQuad::YUVVideoContent: |
| 417 drawYUVVideoQuad(quad->toYUVVideoDrawQuad()); |
| 418 break; |
| 419 } |
| 420 } |
| 421 |
| 422 void LayerRendererChromium::drawCheckerboardQuad(const CCCheckerboardDrawQuad* q
uad) |
| 423 { |
| 424 const TileCheckerboardProgram* program = tileCheckerboardProgram(); |
| 425 ASSERT(program && program->initialized()); |
| 426 GLC(context(), context()->useProgram(program->program())); |
| 427 |
| 428 IntRect tileRect = quad->quadRect(); |
| 429 WebTransformationMatrix tileTransform = quad->quadTransform(); |
| 430 tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y()
+ tileRect.height() / 2.0); |
| 431 |
| 432 float texOffsetX = tileRect.x(); |
| 433 float texOffsetY = tileRect.y(); |
| 434 float texScaleX = tileRect.width(); |
| 435 float texScaleY = tileRect.height(); |
| 436 GLC(context(), context()->uniform4f(program->fragmentShader().texTransformLo
cation(), texOffsetX, texOffsetY, texScaleX, texScaleY)); |
| 437 |
| 438 const int checkerboardWidth = 16; |
| 439 float frequency = 1.0 / checkerboardWidth; |
| 440 |
| 441 GLC(context(), context()->uniform1f(program->fragmentShader().frequencyLocat
ion(), frequency)); |
| 442 |
| 443 float opacity = quad->opacity(); |
| 444 drawTexturedQuad(tileTransform, |
| 445 tileRect.width(), tileRect.height(), opacity, FloatQuad(), |
| 446 program->vertexShader().matrixLocation(), |
| 447 program->fragmentShader().alphaLocation(), -1); |
| 448 } |
| 449 |
| 450 void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* qua
d) |
| 451 { |
| 452 static float glMatrix[16]; |
| 453 const SolidColorProgram* program = solidColorProgram(); |
| 454 ASSERT(program && program->initialized()); |
| 455 GLC(context(), context()->useProgram(program->program())); |
| 456 |
| 457 const IntRect& layerRect = quad->quadRect(); |
| 458 WebTransformationMatrix renderMatrix = quad->quadTransform(); |
| 459 renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerR
ect.height() + layerRect.y()); |
| 460 renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height()); |
| 461 LayerRendererChromium::toGLMatrix(&glMatrix[0], projectionMatrix() * renderM
atrix); |
| 462 GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLoc
ation(), 1, false, &glMatrix[0])); |
| 463 |
| 464 SkColor color = quad->color(); |
| 465 float alpha = SkColorGetA(color) / 255.0; |
| 466 |
| 467 GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(
), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (
SkColorGetB(color) / 255.0) * alpha, alpha)); |
| 468 |
| 469 GLC(context(), context()->lineWidth(quad->width())); |
| 470 |
| 471 // The indices for the line are stored in the same array as the triangle ind
ices. |
| 472 GLC(context(), context()->drawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 6
* sizeof(unsigned short))); |
| 473 } |
| 474 |
| 475 static inline SkBitmap applyFilters(LayerRendererChromium* layerRenderer, const
WebKit::WebFilterOperations& filters, ManagedTexture* sourceTexture) |
| 476 { |
| 477 if (filters.isEmpty()) |
| 478 return SkBitmap(); |
| 479 |
| 480 return SkBitmap(); |
| 481 /* |
| 482 RefPtr<GraphicsContext3D> filterContext = CCProxy::hasImplThread() ? SharedG
raphicsContext3D::getForImplThread() : SharedGraphicsContext3D::get(); |
| 483 if (!filterContext) |
| 484 return SkBitmap(); |
| 485 |
| 486 layerRenderer->context()->flush(); |
| 487 |
| 488 return CCRenderSurfaceFilters::apply(filters, sourceTexture->textureId(), so
urceTexture->size(), filterContext.get()); |
| 489 */ |
| 490 } |
| 491 |
| 492 void LayerRendererChromium::drawBackgroundFilters(const CCRenderPassDrawQuad* qu
ad, const WebTransformationMatrix& contentsDeviceTransform) |
| 493 { |
| 494 // This method draws a background filter, which applies a filter to any pixe
ls behind the quad and seen through its background. |
| 495 // The algorithm works as follows: |
| 496 // 1. Compute a bounding box around the pixels that will be visible through
the quad. |
| 497 // 2. Read the pixels in the bounding box into a buffer R. |
| 498 // 3. Apply the background filter to R, so that it is applied in the pixels'
coordinate space. |
| 499 // 4. Apply the quad's inverse transform to map the pixels in R into the qua
d's content space. This implicitly |
| 500 // clips R by the content bounds of the quad since the destination texture h
as bounds matching the quad's content. |
| 501 // 5. Draw the background texture for the contents using the same transform
as used to draw the contents itself. This is done |
| 502 // without blending to replace the current background pixels with the new fi
ltered background. |
| 503 // 6. Draw the contents of the quad over drop of the new background with ble
nding, as per usual. The filtered background |
| 504 // pixels will show through any non-opaque pixels in this draws. |
| 505 // |
| 506 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5. |
| 507 |
| 508 CCRenderSurface* drawingSurface = quad->renderPass()->targetSurface(); |
| 509 if (quad->backgroundFilters().isEmpty()) |
| 510 return; |
| 511 |
| 512 // FIXME: We only allow background filters on an opaque render surface becau
se other surfaces may contain |
| 513 // translucent pixels, and the contents behind those translucent pixels woul
dn't have the filter applied. |
| 514 if (m_currentRenderPass->hasTransparentBackground()) |
| 515 return; |
| 516 ASSERT(!m_currentManagedTexture); |
| 517 |
| 518 // FIXME: Do a single readback for both the surface and replica and cache th
e filtered results (once filter textures are not reused). |
| 519 IntRect deviceRect = enclosingIntRect(CCMathUtil::mapClippedRect(contentsDev
iceTransform, sharedGeometryQuad().boundingBox())); |
| 520 |
| 521 int top, right, bottom, left; |
| 522 quad->backgroundFilters().getOutsets(top, right, bottom, left); |
| 523 deviceRect.move(-left, -top); |
| 524 deviceRect.expand(left + right, top + bottom); |
| 525 |
| 526 deviceRect.intersect(m_currentRenderPass->framebufferOutputRect()); |
| 527 |
| 528 OwnPtr<ManagedTexture> deviceBackgroundTexture = ManagedTexture::create(m_im
plTextureManager.get()); |
| 529 if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect)) |
| 530 return; |
| 531 |
| 532 SkBitmap filteredDeviceBackground = applyFilters(this, quad->backgroundFilte
rs(), deviceBackgroundTexture.get()); |
| 533 if (!filteredDeviceBackground.getTexture()) |
| 534 return; |
| 535 |
| 536 GrTexture* texture = reinterpret_cast<GrTexture*>(filteredDeviceBackground.g
etTexture()); |
| 537 int filteredDeviceBackgroundTextureId = texture->getTextureHandle(); |
| 538 |
| 539 if (!drawingSurface->prepareBackgroundTexture(this)) |
| 540 return; |
| 541 |
| 542 const CCRenderPass* targetRenderPass = m_currentRenderPass; |
| 543 if (useManagedTexture(drawingSurface->backgroundTexture(), quad->quadRect())
) { |
| 544 // Copy the readback pixels from device to the background texture for th
e surface. |
| 545 WebTransformationMatrix deviceToFramebufferTransform; |
| 546 deviceToFramebufferTransform.translate(quad->quadRect().width() / 2.0, q
uad->quadRect().height() / 2.0); |
| 547 deviceToFramebufferTransform.scale3d(quad->quadRect().width(), quad->qua
dRect().height(), 1); |
| 548 deviceToFramebufferTransform.multiply(contentsDeviceTransform.inverse())
; |
| 549 deviceToFramebufferTransform.translate(deviceRect.width() / 2.0, deviceR
ect.height() / 2.0); |
| 550 deviceToFramebufferTransform.translate(deviceRect.x(), deviceRect.y()); |
| 551 |
| 552 copyTextureToFramebuffer(filteredDeviceBackgroundTextureId, deviceRect.s
ize(), deviceToFramebufferTransform); |
| 553 |
| 554 useRenderPass(targetRenderPass); |
| 555 } |
| 556 } |
| 557 |
| 558 void LayerRendererChromium::drawRenderPassQuad(const CCRenderPassDrawQuad* quad) |
| 559 { |
| 560 // The replica is always drawn first, so free after drawing the contents. |
| 561 bool shouldReleaseTextures = !quad->isReplica(); |
| 562 |
| 563 CCRenderSurface* drawingSurface = quad->renderPass()->targetSurface(); |
| 564 |
| 565 WebTransformationMatrix renderTransform = quad->layerTransform(); |
| 566 // Apply a scaling factor to size the quad from 1x1 to its intended size. |
| 567 renderTransform.scale3d(quad->quadRect().width(), quad->quadRect().height(),
1); |
| 568 WebTransformationMatrix contentsDeviceTransform = WebTransformationMatrix(wi
ndowMatrix() * projectionMatrix() * renderTransform).to2dTransform(); |
| 569 |
| 570 // Can only draw surface if device matrix is invertible. |
| 571 if (!contentsDeviceTransform.isInvertible() || !drawingSurface->hasValidCont
entsTexture()) { |
| 572 if (shouldReleaseTextures) { |
| 573 drawingSurface->releaseBackgroundTexture(); |
| 574 drawingSurface->releaseContentsTexture(); |
| 575 } |
| 576 return; |
| 577 } |
| 578 |
| 579 drawBackgroundFilters(quad, contentsDeviceTransform); |
| 580 |
| 581 // FIXME: Cache this value so that we don't have to do it for both the surfa
ce and its replica. |
| 582 // Apply filters to the contents texture. |
| 583 SkBitmap filterBitmap = applyFilters(this, quad->filters(), drawingSurface->
contentsTexture()); |
| 584 int contentsTextureId = drawingSurface->contentsTexture()->textureId(); |
| 585 if (filterBitmap.getTexture()) { |
| 586 GrTexture* texture = reinterpret_cast<GrTexture*>(filterBitmap.getTextur
e()); |
| 587 contentsTextureId = texture->getTextureHandle(); |
| 588 } |
| 589 |
| 590 // Draw the background texture if there is one. |
| 591 if (drawingSurface->hasValidBackgroundTexture()) |
| 592 copyTextureToFramebuffer(drawingSurface->backgroundTexture()->textureId(
), quad->quadRect().size(), quad->layerTransform()); |
| 593 |
| 594 FloatQuad deviceQuad = contentsDeviceTransform.mapQuad(sharedGeometryQuad())
; |
| 595 CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceQuad.boundingBox
())); |
| 596 CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceQuad); |
| 597 |
| 598 // Use anti-aliasing programs only when necessary. |
| 599 bool useAA = (!deviceQuad.isRectilinear() || !deviceQuad.boundingBox().isExp
ressibleAsIntRect()); |
| 600 if (useAA) { |
| 601 deviceLayerBounds.inflateAntiAliasingDistance(); |
| 602 deviceLayerEdges.inflateAntiAliasingDistance(); |
| 603 } |
| 604 |
| 605 bool useMask = quad->maskTextureId(); |
| 606 |
| 607 // FIXME: use the backgroundTexture and blend the background in with this dr
aw instead of having a separate copy of the background texture. |
| 608 |
| 609 GLC(context(), context()->activeTexture(GL_TEXTURE0)); |
| 610 context()->bindTexture(GL_TEXTURE_2D, contentsTextureId); |
| 611 |
| 612 int shaderQuadLocation = -1; |
| 613 int shaderEdgeLocation = -1; |
| 614 int shaderMaskSamplerLocation = -1; |
| 615 int shaderMatrixLocation = -1; |
| 616 int shaderAlphaLocation = -1; |
| 617 if (useAA && useMask) { |
| 618 const RenderPassMaskProgramAA* program = renderPassMaskProgramAA(); |
| 619 GLC(context(), context()->useProgram(program->program())); |
| 620 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLoc
ation(), 0)); |
| 621 |
| 622 shaderQuadLocation = program->vertexShader().pointLocation(); |
| 623 shaderEdgeLocation = program->fragmentShader().edgeLocation(); |
| 624 shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocatio
n(); |
| 625 shaderMatrixLocation = program->vertexShader().matrixLocation(); |
| 626 shaderAlphaLocation = program->fragmentShader().alphaLocation(); |
| 627 } else if (!useAA && useMask) { |
| 628 const RenderPassMaskProgram* program = renderPassMaskProgram(); |
| 629 GLC(context(), context()->useProgram(program->program())); |
| 630 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLoc
ation(), 0)); |
| 631 |
| 632 shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocatio
n(); |
| 633 shaderMatrixLocation = program->vertexShader().matrixLocation(); |
| 634 shaderAlphaLocation = program->fragmentShader().alphaLocation(); |
| 635 } else if (useAA && !useMask) { |
| 636 const RenderPassProgramAA* program = renderPassProgramAA(); |
| 637 GLC(context(), context()->useProgram(program->program())); |
| 638 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLoc
ation(), 0)); |
| 639 |
| 640 shaderQuadLocation = program->vertexShader().pointLocation(); |
| 641 shaderEdgeLocation = program->fragmentShader().edgeLocation(); |
| 642 shaderMatrixLocation = program->vertexShader().matrixLocation(); |
| 643 shaderAlphaLocation = program->fragmentShader().alphaLocation(); |
| 644 } else { |
| 645 const RenderPassProgram* program = renderPassProgram(); |
| 646 GLC(context(), context()->useProgram(program->program())); |
| 647 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLoc
ation(), 0)); |
| 648 |
| 649 shaderMatrixLocation = program->vertexShader().matrixLocation(); |
| 650 shaderAlphaLocation = program->fragmentShader().alphaLocation(); |
| 651 } |
| 652 |
| 653 if (shaderMaskSamplerLocation != -1) { |
| 654 GLC(context(), context()->activeTexture(GL_TEXTURE1)); |
| 655 GLC(context(), context()->uniform1i(shaderMaskSamplerLocation, 1)); |
| 656 context()->bindTexture(GL_TEXTURE_2D, quad->maskTextureId()); |
| 657 GLC(context(), context()->activeTexture(GL_TEXTURE0)); |
| 658 } |
| 659 |
| 660 if (shaderEdgeLocation != -1) { |
| 661 float edge[24]; |
| 662 deviceLayerEdges.toFloatArray(edge); |
| 663 deviceLayerBounds.toFloatArray(&edge[12]); |
| 664 GLC(context(), context()->uniform3fv(shaderEdgeLocation, 8, edge)); |
| 665 } |
| 666 |
| 667 // Map device space quad to surface space. |
| 668 FloatQuad surfaceQuad = contentsDeviceTransform.inverse().mapQuad(deviceLaye
rEdges.floatQuad()); |
| 669 |
| 670 drawTexturedQuad(quad->layerTransform(), quad->quadRect().width(), quad->qua
dRect().height(), quad->opacity(), surfaceQuad, |
| 671 shaderMatrixLocation, shaderAlphaLocation, shaderQuadLocati
on); |
| 672 |
| 673 if (shouldReleaseTextures) { |
| 674 drawingSurface->releaseBackgroundTexture(); |
| 675 drawingSurface->releaseContentsTexture(); |
| 676 } |
| 677 } |
| 678 |
| 679 void LayerRendererChromium::drawSolidColorQuad(const CCSolidColorDrawQuad* quad) |
| 680 { |
| 681 const SolidColorProgram* program = solidColorProgram(); |
| 682 GLC(context(), context()->useProgram(program->program())); |
| 683 |
| 684 IntRect tileRect = quad->quadRect(); |
| 685 |
| 686 WebTransformationMatrix tileTransform = quad->quadTransform(); |
| 687 tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y()
+ tileRect.height() / 2.0); |
| 688 |
| 689 SkColor color = quad->color(); |
| 690 float opacity = quad->opacity(); |
| 691 float alpha = (SkColorGetA(color) / 255.0) * opacity; |
| 692 |
| 693 GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(
), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (
SkColorGetB(color) / 255.0) * alpha, alpha)); |
| 694 |
| 695 drawTexturedQuad(tileTransform, |
| 696 tileRect.width(), tileRect.height(), 1.0, FloatQuad(), |
| 697 program->vertexShader().matrixLocation(), |
| 698 -1, -1); |
| 699 } |
| 700 |
| 701 struct TileProgramUniforms { |
| 702 unsigned program; |
| 703 unsigned samplerLocation; |
| 704 unsigned vertexTexTransformLocation; |
| 705 unsigned fragmentTexTransformLocation; |
| 706 unsigned edgeLocation; |
| 707 unsigned matrixLocation; |
| 708 unsigned alphaLocation; |
| 709 unsigned pointLocation; |
| 710 }; |
| 711 |
| 712 template<class T> |
| 713 static void tileUniformLocation(T program, TileProgramUniforms& uniforms) |
| 714 { |
| 715 uniforms.program = program->program(); |
| 716 uniforms.vertexTexTransformLocation = program->vertexShader().vertexTexTrans
formLocation(); |
| 717 uniforms.matrixLocation = program->vertexShader().matrixLocation(); |
| 718 uniforms.pointLocation = program->vertexShader().pointLocation(); |
| 719 |
| 720 uniforms.samplerLocation = program->fragmentShader().samplerLocation(); |
| 721 uniforms.alphaLocation = program->fragmentShader().alphaLocation(); |
| 722 uniforms.fragmentTexTransformLocation = program->fragmentShader().fragmentTe
xTransformLocation(); |
| 723 uniforms.edgeLocation = program->fragmentShader().edgeLocation(); |
| 724 } |
| 725 |
| 726 void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad) |
| 727 { |
| 728 const IntRect& tileRect = quad->quadVisibleRect(); |
| 729 |
| 730 FloatRect clampRect(tileRect); |
| 731 // Clamp texture coordinates to avoid sampling outside the layer |
| 732 // by deflating the tile region half a texel or half a texel |
| 733 // minus epsilon for one pixel layers. The resulting clamp region |
| 734 // is mapped to the unit square by the vertex shader and mapped |
| 735 // back to normalized texture coordinates by the fragment shader |
| 736 // after being clamped to 0-1 range. |
| 737 const float epsilon = 1 / 1024.0f; |
| 738 float clampX = min(0.5, clampRect.width() / 2.0 - epsilon); |
| 739 float clampY = min(0.5, clampRect.height() / 2.0 - epsilon); |
| 740 clampRect.inflateX(-clampX); |
| 741 clampRect.inflateY(-clampY); |
| 742 FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).min
XMinYCorner(); |
| 743 |
| 744 FloatPoint textureOffset = quad->textureOffset() + clampOffset + |
| 745 IntPoint(quad->quadVisibleRect().location() - qua
d->quadRect().location()); |
| 746 |
| 747 // Map clamping rectangle to unit square. |
| 748 float vertexTexTranslateX = -clampRect.x() / clampRect.width(); |
| 749 float vertexTexTranslateY = -clampRect.y() / clampRect.height(); |
| 750 float vertexTexScaleX = tileRect.width() / clampRect.width(); |
| 751 float vertexTexScaleY = tileRect.height() / clampRect.height(); |
| 752 |
| 753 // Map to normalized texture coordinates. |
| 754 const IntSize& textureSize = quad->textureSize(); |
| 755 float fragmentTexTranslateX = textureOffset.x() / textureSize.width(); |
| 756 float fragmentTexTranslateY = textureOffset.y() / textureSize.height(); |
| 757 float fragmentTexScaleX = clampRect.width() / textureSize.width(); |
| 758 float fragmentTexScaleY = clampRect.height() / textureSize.height(); |
| 759 |
| 760 |
| 761 FloatQuad localQuad; |
| 762 WebTransformationMatrix deviceTransform = WebTransformationMatrix(windowMatr
ix() * projectionMatrix() * quad->quadTransform()).to2dTransform(); |
| 763 if (!deviceTransform.isInvertible()) |
| 764 return; |
| 765 |
| 766 bool clipped = false; |
| 767 FloatQuad deviceLayerQuad = CCMathUtil::mapQuad(deviceTransform, FloatQuad(q
uad->layerRect()), clipped); |
| 768 |
| 769 TileProgramUniforms uniforms; |
| 770 // For now, we simply skip anti-aliasing with the quad is clipped. This only
happens |
| 771 // on perspective transformed layers that go partially behind the camera. |
| 772 if (quad->isAntialiased() && !clipped) { |
| 773 if (quad->swizzleContents()) |
| 774 tileUniformLocation(tileProgramSwizzleAA(), uniforms); |
| 775 else |
| 776 tileUniformLocation(tileProgramAA(), uniforms); |
| 777 } else { |
| 778 if (quad->needsBlending()) { |
| 779 if (quad->swizzleContents()) |
| 780 tileUniformLocation(tileProgramSwizzle(), uniforms); |
| 781 else |
| 782 tileUniformLocation(tileProgram(), uniforms); |
| 783 } else { |
| 784 if (quad->swizzleContents()) |
| 785 tileUniformLocation(tileProgramSwizzleOpaque(), uniforms); |
| 786 else |
| 787 tileUniformLocation(tileProgramOpaque(), uniforms); |
| 788 } |
| 789 } |
| 790 |
| 791 GLC(context(), context()->useProgram(uniforms.program)); |
| 792 GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0)); |
| 793 GLC(context(), context()->activeTexture(GL_TEXTURE0)); |
| 794 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, quad->textureId())); |
| 795 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER
, quad->textureFilter())); |
| 796 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER
, quad->textureFilter())); |
| 797 |
| 798 |
| 799 if (!clipped && quad->isAntialiased()) { |
| 800 |
| 801 CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceLayerQuad.bo
undingBox())); |
| 802 deviceLayerBounds.inflateAntiAliasingDistance(); |
| 803 |
| 804 CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceLayerQuad); |
| 805 deviceLayerEdges.inflateAntiAliasingDistance(); |
| 806 |
| 807 float edge[24]; |
| 808 deviceLayerEdges.toFloatArray(edge); |
| 809 deviceLayerBounds.toFloatArray(&edge[12]); |
| 810 GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge)); |
| 811 |
| 812 GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation,
vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY)); |
| 813 GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocatio
n, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexS
caleY)); |
| 814 |
| 815 FloatPoint bottomRight(tileRect.maxX(), tileRect.maxY()); |
| 816 FloatPoint bottomLeft(tileRect.x(), tileRect.maxY()); |
| 817 FloatPoint topLeft(tileRect.x(), tileRect.y()); |
| 818 FloatPoint topRight(tileRect.maxX(), tileRect.y()); |
| 819 |
| 820 // Map points to device space. |
| 821 bottomRight = deviceTransform.mapPoint(bottomRight); |
| 822 bottomLeft = deviceTransform.mapPoint(bottomLeft); |
| 823 topLeft = deviceTransform.mapPoint(topLeft); |
| 824 topRight = deviceTransform.mapPoint(topRight); |
| 825 |
| 826 CCLayerQuad::Edge bottomEdge(bottomRight, bottomLeft); |
| 827 CCLayerQuad::Edge leftEdge(bottomLeft, topLeft); |
| 828 CCLayerQuad::Edge topEdge(topLeft, topRight); |
| 829 CCLayerQuad::Edge rightEdge(topRight, bottomRight); |
| 830 |
| 831 // Only apply anti-aliasing to edges not clipped during culling. |
| 832 if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y()) |
| 833 topEdge = deviceLayerEdges.top(); |
| 834 if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x()) |
| 835 leftEdge = deviceLayerEdges.left(); |
| 836 if (quad->rightEdgeAA() && tileRect.maxX() == quad->quadRect().maxX()) |
| 837 rightEdge = deviceLayerEdges.right(); |
| 838 if (quad->bottomEdgeAA() && tileRect.maxY() == quad->quadRect().maxY()) |
| 839 bottomEdge = deviceLayerEdges.bottom(); |
| 840 |
| 841 float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1; |
| 842 bottomEdge.scale(sign); |
| 843 leftEdge.scale(sign); |
| 844 topEdge.scale(sign); |
| 845 rightEdge.scale(sign); |
| 846 |
| 847 // Create device space quad. |
| 848 CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge); |
| 849 |
| 850 // Map quad to layer space. |
| 851 WebTransformationMatrix inverseDeviceTransform = deviceTransform.inverse
(); |
| 852 localQuad = inverseDeviceTransform.mapQuad(deviceQuad.floatQuad()); |
| 853 } else { |
| 854 // Move fragment shader transform to vertex shader. We can do this while |
| 855 // still producing correct results as fragmentTexTransformLocation |
| 856 // should always be non-negative when tiles are transformed in a way |
| 857 // that could result in sampling outside the layer. |
| 858 vertexTexScaleX *= fragmentTexScaleX; |
| 859 vertexTexScaleY *= fragmentTexScaleY; |
| 860 vertexTexTranslateX *= fragmentTexScaleX; |
| 861 vertexTexTranslateY *= fragmentTexScaleY; |
| 862 vertexTexTranslateX += fragmentTexTranslateX; |
| 863 vertexTexTranslateY += fragmentTexTranslateY; |
| 864 |
| 865 GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation,
vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY)); |
| 866 |
| 867 localQuad = FloatRect(tileRect); |
| 868 } |
| 869 |
| 870 // Normalize to tileRect. |
| 871 localQuad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height()); |
| 872 |
| 873 drawTexturedQuad(quad->quadTransform(), tileRect.width(), tileRect.height(),
quad->opacity(), localQuad, uniforms.matrixLocation, uniforms.alphaLocation, un
iforms.pointLocation); |
| 874 } |
| 875 |
| 876 void LayerRendererChromium::drawYUVVideoQuad(const CCYUVVideoDrawQuad* quad) |
| 877 { |
| 878 const VideoYUVProgram* program = videoYUVProgram(); |
| 879 ASSERT(program && program->initialized()); |
| 880 |
| 881 const CCVideoLayerImpl::FramePlane& yPlane = quad->yPlane(); |
| 882 const CCVideoLayerImpl::FramePlane& uPlane = quad->uPlane(); |
| 883 const CCVideoLayerImpl::FramePlane& vPlane = quad->vPlane(); |
| 884 |
| 885 GLC(context(), context()->activeTexture(GL_TEXTURE1)); |
| 886 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, yPlane.textureId)); |
| 887 GLC(context(), context()->activeTexture(GL_TEXTURE2)); |
| 888 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, uPlane.textureId)); |
| 889 GLC(context(), context()->activeTexture(GL_TEXTURE3)); |
| 890 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, vPlane.textureId)); |
| 891 |
| 892 GLC(context(), context()->useProgram(program->program())); |
| 893 |
| 894 float yWidthScaleFactor = static_cast<float>(yPlane.visibleSize.width()) / y
Plane.size.width(); |
| 895 // Arbitrarily take the u sizes because u and v dimensions are identical. |
| 896 float uvWidthScaleFactor = static_cast<float>(uPlane.visibleSize.width()) /
uPlane.size.width(); |
| 897 GLC(context(), context()->uniform1f(program->vertexShader().yWidthScaleFacto
rLocation(), yWidthScaleFactor)); |
| 898 GLC(context(), context()->uniform1f(program->vertexShader().uvWidthScaleFact
orLocation(), uvWidthScaleFactor)); |
| 899 |
| 900 GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocati
on(), 1)); |
| 901 GLC(context(), context()->uniform1i(program->fragmentShader().uTextureLocati
on(), 2)); |
| 902 GLC(context(), context()->uniform1i(program->fragmentShader().vTextureLocati
on(), 3)); |
| 903 |
| 904 // These values are magic numbers that are used in the transformation from Y
UV to RGB color values. |
| 905 // They are taken from the following webpage: http://www.fourcc.org/fccyvrgb
.php |
| 906 float yuv2RGB[9] = { |
| 907 1.164f, 1.164f, 1.164f, |
| 908 0.f, -.391f, 2.018f, |
| 909 1.596f, -.813f, 0.f, |
| 910 }; |
| 911 GLC(context(), context()->uniformMatrix3fv(program->fragmentShader().ccMatri
xLocation(), 1, 0, yuv2RGB)); |
| 912 |
| 913 // These values map to 16, 128, and 128 respectively, and are computed |
| 914 // as a fraction over 256 (e.g. 16 / 256 = 0.0625). |
| 915 // They are used in the YUV to RGBA conversion formula: |
| 916 // Y - 16 : Gives 16 values of head and footroom for overshooting |
| 917 // U - 128 : Turns unsigned U into signed U [-128,127] |
| 918 // V - 128 : Turns unsigned V into signed V [-128,127] |
| 919 float yuvAdjust[3] = { |
| 920 -0.0625f, |
| 921 -0.5f, |
| 922 -0.5f, |
| 923 }; |
| 924 GLC(context(), context()->uniform3fv(program->fragmentShader().yuvAdjLocatio
n(), 1, yuvAdjust)); |
| 925 |
| 926 const IntSize& bounds = quad->quadRect().size(); |
| 927 drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), qu
ad->opacity(), FloatQuad(), |
| 928 program->vertexShader().matrixLocation(), |
| 929 program->fragmentShader().alphaLocation(), |
| 930 -1); |
| 931 |
| 932 // Reset active texture back to texture 0. |
| 933 GLC(context(), context()->activeTexture(GL_TEXTURE0)); |
| 934 } |
| 935 |
| 936 void LayerRendererChromium::drawStreamVideoQuad(const CCStreamVideoDrawQuad* qua
d) |
| 937 { |
| 938 static float glMatrix[16]; |
| 939 |
| 940 ASSERT(m_capabilities.usingEglImage); |
| 941 |
| 942 const VideoStreamTextureProgram* program = videoStreamTextureProgram(); |
| 943 GLC(context(), context()->useProgram(program->program())); |
| 944 |
| 945 toGLMatrix(&glMatrix[0], quad->matrix()); |
| 946 GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrix
Location(), 1, false, glMatrix)); |
| 947 |
| 948 GLC(context(), context()->activeTexture(GL_TEXTURE0)); |
| 949 GLC(context(), context()->bindTexture(GL_TEXTURE_EXTERNAL_OES, quad->texture
Id())); |
| 950 |
| 951 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocatio
n(), 0)); |
| 952 |
| 953 const IntSize& bounds = quad->quadRect().size(); |
| 954 drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), qu
ad->opacity(), sharedGeometryQuad(), |
| 955 program->vertexShader().matrixLocation(), |
| 956 program->fragmentShader().alphaLocation(), |
| 957 -1); |
| 958 } |
| 959 |
| 960 struct TextureProgramBinding { |
| 961 template<class Program> void set(Program* program) |
| 962 { |
| 963 ASSERT(program && program->initialized()); |
| 964 programId = program->program(); |
| 965 samplerLocation = program->fragmentShader().samplerLocation(); |
| 966 matrixLocation = program->vertexShader().matrixLocation(); |
| 967 alphaLocation = program->fragmentShader().alphaLocation(); |
| 968 } |
| 969 int programId; |
| 970 int samplerLocation; |
| 971 int matrixLocation; |
| 972 int alphaLocation; |
| 973 }; |
| 974 |
| 975 struct TexTransformTextureProgramBinding : TextureProgramBinding { |
| 976 template<class Program> void set(Program* program) |
| 977 { |
| 978 TextureProgramBinding::set(program); |
| 979 texTransformLocation = program->vertexShader().texTransformLocation(); |
| 980 } |
| 981 int texTransformLocation; |
| 982 }; |
| 983 |
| 984 void LayerRendererChromium::drawTextureQuad(const CCTextureDrawQuad* quad) |
| 985 { |
| 986 ASSERT(CCProxy::isImplThread()); |
| 987 |
| 988 TexTransformTextureProgramBinding binding; |
| 989 if (quad->flipped()) |
| 990 binding.set(textureProgramFlip()); |
| 991 else |
| 992 binding.set(textureProgram()); |
| 993 GLC(context(), context()->useProgram(binding.programId)); |
| 994 GLC(context(), context()->uniform1i(binding.samplerLocation, 0)); |
| 995 const FloatRect& uvRect = quad->uvRect(); |
| 996 GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x()
, uvRect.y(), uvRect.width(), uvRect.height())); |
| 997 |
| 998 GLC(context(), context()->activeTexture(GL_TEXTURE0)); |
| 999 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, quad->textureId())); |
| 1000 |
| 1001 // FIXME: setting the texture parameters every time is redundant. Move this
code somewhere |
| 1002 // where it will only happen once per texture. |
| 1003 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER
, GL_LINEAR)); |
| 1004 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER
, GL_LINEAR)); |
| 1005 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL
_CLAMP_TO_EDGE)); |
| 1006 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL
_CLAMP_TO_EDGE)); |
| 1007 |
| 1008 if (!quad->premultipliedAlpha()) |
| 1009 GLC(context(), context()->blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
)); |
| 1010 |
| 1011 WebTransformationMatrix quadTransform = quad->quadTransform(); |
| 1012 IntRect quadRect = quad->quadRect(); |
| 1013 quadTransform.translate(quadRect.x() + quadRect.width() / 2.0, quadRect.y()
+ quadRect.height() / 2.0); |
| 1014 |
| 1015 drawTexturedQuad(quadTransform, quadRect.width(), quadRect.height(), quad->o
pacity(), sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -
1); |
| 1016 |
| 1017 if (!quad->premultipliedAlpha()) |
| 1018 GLC(m_context, m_context->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); |
| 1019 } |
| 1020 |
| 1021 void LayerRendererChromium::drawIOSurfaceQuad(const CCIOSurfaceDrawQuad* quad) |
| 1022 { |
| 1023 ASSERT(CCProxy::isImplThread()); |
| 1024 TexTransformTextureProgramBinding binding; |
| 1025 binding.set(textureIOSurfaceProgram()); |
| 1026 |
| 1027 GLC(context(), context()->useProgram(binding.programId)); |
| 1028 GLC(context(), context()->uniform1i(binding.samplerLocation, 0)); |
| 1029 GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad
->ioSurfaceSize().width(), quad->ioSurfaceSize().height())); |
| 1030 |
| 1031 GLC(context(), context()->activeTexture(GL_TEXTURE0)); |
| 1032 GLC(context(), context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB, quad->ioSurf
aceTextureId())); |
| 1033 |
| 1034 // FIXME: setting the texture parameters every time is redundant. Move this
code somewhere |
| 1035 // where it will only happen once per texture. |
| 1036 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER
, GL_LINEAR)); |
| 1037 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER
, GL_LINEAR)); |
| 1038 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL
_CLAMP_TO_EDGE)); |
| 1039 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL
_CLAMP_TO_EDGE)); |
| 1040 |
| 1041 const IntSize& bounds = quad->quadRect().size(); |
| 1042 |
| 1043 drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), qu
ad->opacity(), sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocati
on, -1); |
| 1044 |
| 1045 GLC(context(), context()->bindTexture(GL_TEXTURE_RECTANGLE_ARB, 0)); |
| 1046 } |
| 1047 |
| 1048 void LayerRendererChromium::drawHeadsUpDisplay(ManagedTexture* hudTexture, const
IntSize& hudSize) |
| 1049 { |
| 1050 GLC(m_context, m_context->enable(GL_BLEND)); |
| 1051 GLC(m_context, m_context->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); |
| 1052 GLC(m_context, m_context->disable(GL_SCISSOR_TEST)); |
| 1053 useRenderPass(m_defaultRenderPass); |
| 1054 |
| 1055 const HeadsUpDisplayProgram* program = headsUpDisplayProgram(); |
| 1056 ASSERT(program && program->initialized()); |
| 1057 GLC(m_context, m_context->activeTexture(GL_TEXTURE0)); |
| 1058 if (!hudTexture->textureId()) |
| 1059 hudTexture->allocate(m_implTextureAllocator.get()); |
| 1060 GLC(m_context, m_context->bindTexture(GL_TEXTURE_2D, hudTexture->textureId()
)); |
| 1061 GLC(m_context, m_context->useProgram(program->program())); |
| 1062 GLC(m_context, m_context->uniform1i(program->fragmentShader().samplerLocatio
n(), 0)); |
| 1063 |
| 1064 WebTransformationMatrix matrix; |
| 1065 matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0); |
| 1066 drawTexturedQuad(matrix, hudSize.width(), hudSize.height(), |
| 1067 1, sharedGeometryQuad(), program->vertexShader().matrixLoca
tion(), |
| 1068 program->fragmentShader().alphaLocation(), |
| 1069 -1); |
| 1070 } |
| 1071 |
| 1072 void LayerRendererChromium::finishDrawingFrame() |
| 1073 { |
| 1074 GLC(m_context, m_context->disable(GL_SCISSOR_TEST)); |
| 1075 GLC(m_context, m_context->disable(GL_BLEND)); |
| 1076 |
| 1077 m_implTextureManager->unprotectAllTextures(); |
| 1078 m_implTextureManager->deleteEvictedTextures(m_implTextureAllocator.get()); |
| 1079 } |
| 1080 |
| 1081 void LayerRendererChromium::toGLMatrix(float* flattened, const WebTransformation
Matrix& m) |
| 1082 { |
| 1083 flattened[0] = m.m11(); |
| 1084 flattened[1] = m.m12(); |
| 1085 flattened[2] = m.m13(); |
| 1086 flattened[3] = m.m14(); |
| 1087 flattened[4] = m.m21(); |
| 1088 flattened[5] = m.m22(); |
| 1089 flattened[6] = m.m23(); |
| 1090 flattened[7] = m.m24(); |
| 1091 flattened[8] = m.m31(); |
| 1092 flattened[9] = m.m32(); |
| 1093 flattened[10] = m.m33(); |
| 1094 flattened[11] = m.m34(); |
| 1095 flattened[12] = m.m41(); |
| 1096 flattened[13] = m.m42(); |
| 1097 flattened[14] = m.m43(); |
| 1098 flattened[15] = m.m44(); |
| 1099 } |
| 1100 |
| 1101 void LayerRendererChromium::drawTexturedQuad(const WebTransformationMatrix& draw
Matrix, |
| 1102 float width, float height, float op
acity, const FloatQuad& quad, |
| 1103 int matrixLocation, int alphaLocati
on, int quadLocation) |
| 1104 { |
| 1105 static float glMatrix[16]; |
| 1106 |
| 1107 WebTransformationMatrix renderMatrix = drawMatrix; |
| 1108 |
| 1109 // Apply a scaling factor to size the quad from 1x1 to its intended size. |
| 1110 renderMatrix.scale3d(width, height, 1); |
| 1111 |
| 1112 // Apply the projection matrix before sending the transform over to the shad
er. |
| 1113 toGLMatrix(&glMatrix[0], m_projectionMatrix * renderMatrix); |
| 1114 |
| 1115 GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatr
ix[0])); |
| 1116 |
| 1117 if (quadLocation != -1) { |
| 1118 float point[8]; |
| 1119 point[0] = quad.p1().x(); |
| 1120 point[1] = quad.p1().y(); |
| 1121 point[2] = quad.p2().x(); |
| 1122 point[3] = quad.p2().y(); |
| 1123 point[4] = quad.p3().x(); |
| 1124 point[5] = quad.p3().y(); |
| 1125 point[6] = quad.p4().x(); |
| 1126 point[7] = quad.p4().y(); |
| 1127 GLC(m_context, m_context->uniform2fv(quadLocation, 4, point)); |
| 1128 } |
| 1129 |
| 1130 if (alphaLocation != -1) |
| 1131 GLC(m_context, m_context->uniform1f(alphaLocation, opacity)); |
| 1132 |
| 1133 GLC(m_context, m_context->drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0
)); |
| 1134 } |
| 1135 |
| 1136 void LayerRendererChromium::copyTextureToFramebuffer(int textureId, const IntSiz
e& bounds, const WebTransformationMatrix& drawMatrix) |
| 1137 { |
| 1138 const RenderPassProgram* program = renderPassProgram(); |
| 1139 |
| 1140 GLC(context(), context()->activeTexture(GL_TEXTURE0)); |
| 1141 GLC(context(), context()->bindTexture(GL_TEXTURE_2D, textureId)); |
| 1142 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER
, GL_LINEAR)); |
| 1143 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER
, GL_LINEAR)); |
| 1144 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL
_CLAMP_TO_EDGE)); |
| 1145 GLC(context(), context()->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL
_CLAMP_TO_EDGE)); |
| 1146 |
| 1147 GLC(context(), context()->useProgram(program->program())); |
| 1148 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocatio
n(), 0)); |
| 1149 drawTexturedQuad(drawMatrix, bounds.width(), bounds.height(), 1, sharedGeome
tryQuad(), |
| 1150 program->vertexShader().matrixLocation(), |
| 1151 program->fragmentShader().alphaLocation(), |
| 1152 -1); |
| 1153 } |
| 1154 |
| 1155 void LayerRendererChromium::finish() |
| 1156 { |
| 1157 TRACE_EVENT0("cc", "LayerRendererChromium::finish"); |
| 1158 m_context->finish(); |
| 1159 } |
| 1160 |
| 1161 bool LayerRendererChromium::swapBuffers(const IntRect& subBuffer) |
| 1162 { |
| 1163 ASSERT(m_visible); |
| 1164 ASSERT(!m_isFramebufferDiscarded); |
| 1165 |
| 1166 TRACE_EVENT0("cc", "LayerRendererChromium::swapBuffers"); |
| 1167 // We're done! Time to swapbuffers! |
| 1168 |
| 1169 if (m_capabilities.usingPartialSwap) { |
| 1170 // If supported, we can save significant bandwidth by only swapping the
damaged/scissored region (clamped to the viewport) |
| 1171 IntRect clippedSubBuffer = subBuffer; |
| 1172 clippedSubBuffer.intersect(IntRect(IntPoint::zero(), viewportSize())); |
| 1173 int flippedYPosOfRectBottom = viewportHeight() - clippedSubBuffer.y() -
clippedSubBuffer.height(); |
| 1174 m_context->postSubBufferCHROMIUM(clippedSubBuffer.x(), flippedYPosOfRect
Bottom, clippedSubBuffer.width(), clippedSubBuffer.height()); |
| 1175 } else |
| 1176 // Note that currently this has the same effect as swapBuffers; we shoul
d |
| 1177 // consider exposing a different entry point on WebGraphicsContext3D. |
| 1178 m_context->prepareTexture(); |
| 1179 |
| 1180 return true; |
| 1181 } |
| 1182 |
| 1183 void LayerRendererChromium::onSwapBuffersComplete() |
| 1184 { |
| 1185 m_client->onSwapBuffersComplete(); |
| 1186 } |
| 1187 |
| 1188 void LayerRendererChromium::onMemoryAllocationChanged(WebGraphicsMemoryAllocatio
n allocation) |
| 1189 { |
| 1190 // FIXME: This is called on the main thread in single threaded mode, but we
expect it on the impl thread. |
| 1191 if (!CCProxy::hasImplThread()) { |
| 1192 ASSERT(CCProxy::isMainThread()); |
| 1193 DebugScopedSetImplThread impl; |
| 1194 onMemoryAllocationChangedOnImplThread(allocation); |
| 1195 } else { |
| 1196 ASSERT(CCProxy::isImplThread()); |
| 1197 onMemoryAllocationChangedOnImplThread(allocation); |
| 1198 } |
| 1199 } |
| 1200 |
| 1201 void LayerRendererChromium::onMemoryAllocationChangedOnImplThread(WebKit::WebGra
phicsMemoryAllocation allocation) |
| 1202 { |
| 1203 if (m_visible && !allocation.gpuResourceSizeInBytes) |
| 1204 return; |
| 1205 |
| 1206 if (!allocation.suggestHaveBackbuffer && !m_visible) |
| 1207 discardFramebuffer(); |
| 1208 |
| 1209 if (!allocation.gpuResourceSizeInBytes) { |
| 1210 releaseRenderPassTextures(); |
| 1211 m_client->releaseContentsTextures(); |
| 1212 GLC(m_context, m_context->flush()); |
| 1213 } else |
| 1214 m_client->setMemoryAllocationLimitBytes(allocation.gpuResourceSizeInByte
s); |
| 1215 } |
| 1216 |
| 1217 void LayerRendererChromium::discardFramebuffer() |
| 1218 { |
| 1219 if (m_isFramebufferDiscarded) |
| 1220 return; |
| 1221 |
| 1222 if (!m_capabilities.usingDiscardFramebuffer) |
| 1223 return; |
| 1224 |
| 1225 // FIXME: Update attachments argument to appropriate values once they are no
longer ignored. |
| 1226 m_context->discardFramebufferEXT(GL_TEXTURE_2D, 0, 0); |
| 1227 m_isFramebufferDiscarded = true; |
| 1228 |
| 1229 // Damage tracker needs a full reset every time framebuffer is discarded. |
| 1230 m_client->setFullRootLayerDamage(); |
| 1231 } |
| 1232 |
| 1233 void LayerRendererChromium::ensureFramebuffer() |
| 1234 { |
| 1235 if (!m_isFramebufferDiscarded) |
| 1236 return; |
| 1237 |
| 1238 if (!m_capabilities.usingDiscardFramebuffer) |
| 1239 return; |
| 1240 |
| 1241 m_context->ensureFramebufferCHROMIUM(); |
| 1242 m_isFramebufferDiscarded = false; |
| 1243 } |
| 1244 |
| 1245 void LayerRendererChromium::onContextLost() |
| 1246 { |
| 1247 m_client->didLoseContext(); |
| 1248 } |
| 1249 |
| 1250 |
| 1251 void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& re
ct) |
| 1252 { |
| 1253 ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight()); |
| 1254 |
| 1255 if (!pixels) |
| 1256 return; |
| 1257 |
| 1258 makeContextCurrent(); |
| 1259 |
| 1260 bool doWorkaround = needsIOSurfaceReadbackWorkaround(); |
| 1261 |
| 1262 Platform3DObject temporaryTexture = 0; |
| 1263 Platform3DObject temporaryFBO = 0; |
| 1264 |
| 1265 if (doWorkaround) { |
| 1266 // On Mac OS X, calling glReadPixels against an FBO whose color attachme
nt is an |
| 1267 // IOSurface-backed texture causes corruption of future glReadPixels cal
ls, even those on |
| 1268 // different OpenGL contexts. It is believed that this is the root cause
of top crasher |
| 1269 // http://crbug.com/99393. <rdar://problem/10949687> |
| 1270 |
| 1271 temporaryTexture = m_context->createTexture(); |
| 1272 GLC(m_context, m_context->bindTexture(GL_TEXTURE_2D, temporaryTexture)); |
| 1273 GLC(m_context, m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FI
LTER, GL_LINEAR)); |
| 1274 GLC(m_context, m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FI
LTER, GL_LINEAR)); |
| 1275 GLC(m_context, m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE)); |
| 1276 GLC(m_context, m_context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE)); |
| 1277 // Copy the contents of the current (IOSurface-backed) framebuffer into
a temporary texture. |
| 1278 GLC(m_context, m_context->copyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0
, rect.maxX(), rect.maxY(), 0)); |
| 1279 temporaryFBO = m_context->createFramebuffer(); |
| 1280 // Attach this texture to an FBO, and perform the readback from that FBO
. |
| 1281 GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, temporaryFBO))
; |
| 1282 GLC(m_context, m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_
ATTACHMENT0, GL_TEXTURE_2D, temporaryTexture, 0)); |
| 1283 |
| 1284 ASSERT(m_context->checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFF
ER_COMPLETE); |
| 1285 } |
| 1286 |
| 1287 GLC(m_context, m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.
height(), |
| 1288 GL_RGBA, GL_UNSIGNED_BYTE, pixels)); |
| 1289 |
| 1290 if (doWorkaround) { |
| 1291 // Clean up. |
| 1292 GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0)); |
| 1293 GLC(m_context, m_context->bindTexture(GL_TEXTURE_2D, 0)); |
| 1294 GLC(m_context, m_context->deleteFramebuffer(temporaryFBO)); |
| 1295 GLC(m_context, m_context->deleteTexture(temporaryTexture)); |
| 1296 } |
| 1297 |
| 1298 if (!m_visible) { |
| 1299 TRACE_EVENT0("cc", "LayerRendererChromium::getFramebufferPixels dropping
resources after readback"); |
| 1300 discardFramebuffer(); |
| 1301 releaseRenderPassTextures(); |
| 1302 m_client->releaseContentsTextures(); |
| 1303 GLC(m_context, m_context->flush()); |
| 1304 } |
| 1305 } |
| 1306 |
| 1307 bool LayerRendererChromium::getFramebufferTexture(ManagedTexture* texture, const
IntRect& deviceRect) |
| 1308 { |
| 1309 if (!texture->reserve(deviceRect.size(), GL_RGB)) |
| 1310 return false; |
| 1311 |
| 1312 if (!texture->textureId()) |
| 1313 texture->allocate(m_implTextureAllocator.get()); |
| 1314 GLC(m_context, m_context->bindTexture(GL_TEXTURE_2D, texture->textureId())); |
| 1315 GLC(m_context, m_context->copyTexImage2D(GL_TEXTURE_2D, 0, texture->format()
, |
| 1316 deviceRect.x(), deviceRect.y(), dev
iceRect.width(), deviceRect.height(), 0)); |
| 1317 return true; |
| 1318 } |
| 1319 |
| 1320 bool LayerRendererChromium::isCurrentRenderPass(const CCRenderPass* renderPass) |
| 1321 { |
| 1322 return m_currentRenderPass == renderPass && !m_currentManagedTexture; |
| 1323 } |
| 1324 |
| 1325 bool LayerRendererChromium::useRenderPass(const CCRenderPass* renderPass) |
| 1326 { |
| 1327 m_currentRenderPass = renderPass; |
| 1328 m_currentManagedTexture = 0; |
| 1329 |
| 1330 if (renderPass == m_defaultRenderPass) { |
| 1331 GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, 0)); |
| 1332 setDrawFramebufferRect(renderPass->framebufferOutputRect(), true); |
| 1333 return true; |
| 1334 } |
| 1335 |
| 1336 if (!renderPass->targetSurface()->prepareContentsTexture(this)) |
| 1337 return false; |
| 1338 |
| 1339 return bindFramebufferToTexture(renderPass->targetSurface()->contentsTexture
(), renderPass->framebufferOutputRect()); |
| 1340 } |
| 1341 |
| 1342 bool LayerRendererChromium::useManagedTexture(ManagedTexture* texture, const Int
Rect& viewportRect) |
| 1343 { |
| 1344 m_currentRenderPass = 0; |
| 1345 m_currentManagedTexture = texture; |
| 1346 |
| 1347 return bindFramebufferToTexture(texture, viewportRect); |
| 1348 } |
| 1349 |
| 1350 bool LayerRendererChromium::bindFramebufferToTexture(ManagedTexture* texture, co
nst IntRect& framebufferRect) |
| 1351 { |
| 1352 GLC(m_context, m_context->bindFramebuffer(GL_FRAMEBUFFER, m_offscreenFramebu
fferId)); |
| 1353 |
| 1354 if (!texture->textureId()) |
| 1355 texture->allocate(m_implTextureAllocator.get()); |
| 1356 GLC(m_context, m_context->framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTA
CHMENT0, GL_TEXTURE_2D, texture->textureId(), 0)); |
| 1357 |
| 1358 #if !defined ( NDEBUG ) |
| 1359 if (m_context->checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMP
LETE) { |
| 1360 ASSERT_NOT_REACHED(); |
| 1361 return false; |
| 1362 } |
| 1363 #endif |
| 1364 |
| 1365 setDrawFramebufferRect(framebufferRect, false); |
| 1366 |
| 1367 return true; |
| 1368 } |
| 1369 |
| 1370 // Sets the scissor region to the given rectangle. The coordinate system for the |
| 1371 // scissorRect has its origin at the top left corner of the current visible rect
. |
| 1372 void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect) |
| 1373 { |
| 1374 IntRect framebufferOutputRect = (m_currentRenderPass ? m_currentRenderPass->
framebufferOutputRect() : m_defaultRenderPass->framebufferOutputRect()); |
| 1375 |
| 1376 GLC(m_context, m_context->enable(GL_SCISSOR_TEST)); |
| 1377 |
| 1378 // The scissor coordinates must be supplied in viewport space so we need to
offset |
| 1379 // by the relative position of the top left corner of the current render pas
s. |
| 1380 int scissorX = scissorRect.x() - framebufferOutputRect.x(); |
| 1381 // When rendering to the default render surface we're rendering upside down
so the top |
| 1382 // of the GL scissor is the bottom of our layer. |
| 1383 // But, if rendering to offscreen texture, we reverse our sense of 'upside d
own'. |
| 1384 int scissorY; |
| 1385 if (isCurrentRenderPass(m_defaultRenderPass)) |
| 1386 scissorY = framebufferOutputRect.height() - (scissorRect.maxY() - frameb
ufferOutputRect.y()); |
| 1387 else |
| 1388 scissorY = scissorRect.y() - framebufferOutputRect.y(); |
| 1389 GLC(m_context, m_context->scissor(scissorX, scissorY, scissorRect.width(), s
cissorRect.height())); |
| 1390 } |
| 1391 |
| 1392 bool LayerRendererChromium::makeContextCurrent() |
| 1393 { |
| 1394 return m_context->makeContextCurrent(); |
| 1395 } |
| 1396 |
| 1397 // Sets the coordinate range of content that ends being drawn onto the target re
nder surface. |
| 1398 // The target render surface is assumed to have an origin at 0, 0 and the width
and height of |
| 1399 // of the drawRect. |
| 1400 void LayerRendererChromium::setDrawFramebufferRect(const IntRect& drawRect, bool
flipY) |
| 1401 { |
| 1402 if (flipY) |
| 1403 m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect
.maxY(), drawRect.y()); |
| 1404 else |
| 1405 m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect
.y(), drawRect.maxY()); |
| 1406 GLC(m_context, m_context->viewport(0, 0, drawRect.width(), drawRect.height()
)); |
| 1407 m_windowMatrix = screenMatrix(0, 0, drawRect.width(), drawRect.height()); |
| 1408 } |
| 1409 |
| 1410 |
| 1411 bool LayerRendererChromium::initializeSharedObjects() |
| 1412 { |
| 1413 TRACE_EVENT0("cc", "LayerRendererChromium::initializeSharedObjects"); |
| 1414 makeContextCurrent(); |
| 1415 |
| 1416 // Create an FBO for doing offscreen rendering. |
| 1417 GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer()); |
| 1418 |
| 1419 // We will always need these programs to render, so create the programs eage
rly so that the shader compilation can |
| 1420 // start while we do other work. Other programs are created lazily on first
access. |
| 1421 m_sharedGeometry = adoptPtr(new GeometryBinding(m_context)); |
| 1422 m_renderPassProgram = adoptPtr(new RenderPassProgram(m_context)); |
| 1423 m_tileProgram = adoptPtr(new TileProgram(m_context)); |
| 1424 m_tileProgramOpaque = adoptPtr(new TileProgramOpaque(m_context)); |
| 1425 |
| 1426 GLC(m_context, m_context->flush()); |
| 1427 |
| 1428 m_implTextureManager = TextureManager::create(TextureManager::highLimitBytes
(viewportSize()), |
| 1429 TextureManager::reclaimLimitBy
tes(viewportSize()), |
| 1430 m_capabilities.maxTextureSize)
; |
| 1431 m_textureCopier = AcceleratedTextureCopier::create(m_context); |
| 1432 if (m_textureUploaderSetting == ThrottledUploader) |
| 1433 m_textureUploader = ThrottledTextureUploader::create(m_context); |
| 1434 else |
| 1435 m_textureUploader = UnthrottledTextureUploader::create(); |
| 1436 m_contentsTextureAllocator = TrackingTextureAllocator::create(m_context); |
| 1437 m_implTextureAllocator = TrackingTextureAllocator::create(m_context); |
| 1438 if (m_capabilities.usingTextureUsageHint) |
| 1439 m_implTextureAllocator->setTextureUsageHint(TrackingTextureAllocator::Fr
amebufferAttachment); |
| 1440 if (m_capabilities.usingTextureStorageExtension) { |
| 1441 m_contentsTextureAllocator->setUseTextureStorageExt(true); |
| 1442 m_implTextureAllocator->setUseTextureStorageExt(true); |
| 1443 } |
| 1444 |
| 1445 return true; |
| 1446 } |
| 1447 |
| 1448 const LayerRendererChromium::TileCheckerboardProgram* LayerRendererChromium::til
eCheckerboardProgram() |
| 1449 { |
| 1450 if (!m_tileCheckerboardProgram) |
| 1451 m_tileCheckerboardProgram = adoptPtr(new TileCheckerboardProgram(m_conte
xt)); |
| 1452 if (!m_tileCheckerboardProgram->initialized()) { |
| 1453 TRACE_EVENT0("cc", "LayerRendererChromium::checkerboardProgram::initaliz
e"); |
| 1454 m_tileCheckerboardProgram->initialize(m_context); |
| 1455 } |
| 1456 return m_tileCheckerboardProgram.get(); |
| 1457 } |
| 1458 |
| 1459 const LayerRendererChromium::SolidColorProgram* LayerRendererChromium::solidColo
rProgram() |
| 1460 { |
| 1461 if (!m_solidColorProgram) |
| 1462 m_solidColorProgram = adoptPtr(new SolidColorProgram(m_context)); |
| 1463 if (!m_solidColorProgram->initialized()) { |
| 1464 TRACE_EVENT0("cc", "LayerRendererChromium::solidColorProgram::initialize
"); |
| 1465 m_solidColorProgram->initialize(m_context); |
| 1466 } |
| 1467 return m_solidColorProgram.get(); |
| 1468 } |
| 1469 |
| 1470 const LayerRendererChromium::HeadsUpDisplayProgram* LayerRendererChromium::heads
UpDisplayProgram() |
| 1471 { |
| 1472 if (!m_headsUpDisplayProgram) |
| 1473 m_headsUpDisplayProgram = adoptPtr(new HeadsUpDisplayProgram(m_context))
; |
| 1474 if (!m_headsUpDisplayProgram->initialized()) { |
| 1475 TRACE_EVENT0("cc", "LayerRendererChromium::headsUpDisplayProgram::initia
lize"); |
| 1476 m_headsUpDisplayProgram->initialize(m_context); |
| 1477 } |
| 1478 return m_headsUpDisplayProgram.get(); |
| 1479 } |
| 1480 |
| 1481 const LayerRendererChromium::RenderPassProgram* LayerRendererChromium::renderPas
sProgram() |
| 1482 { |
| 1483 ASSERT(m_renderPassProgram); |
| 1484 if (!m_renderPassProgram->initialized()) { |
| 1485 TRACE_EVENT0("cc", "LayerRendererChromium::renderPassProgram::initialize
"); |
| 1486 m_renderPassProgram->initialize(m_context); |
| 1487 } |
| 1488 return m_renderPassProgram.get(); |
| 1489 } |
| 1490 |
| 1491 const LayerRendererChromium::RenderPassProgramAA* LayerRendererChromium::renderP
assProgramAA() |
| 1492 { |
| 1493 if (!m_renderPassProgramAA) |
| 1494 m_renderPassProgramAA = adoptPtr(new RenderPassProgramAA(m_context)); |
| 1495 if (!m_renderPassProgramAA->initialized()) { |
| 1496 TRACE_EVENT0("cc", "LayerRendererChromium::renderPassProgramAA::initiali
ze"); |
| 1497 m_renderPassProgramAA->initialize(m_context); |
| 1498 } |
| 1499 return m_renderPassProgramAA.get(); |
| 1500 } |
| 1501 |
| 1502 const LayerRendererChromium::RenderPassMaskProgram* LayerRendererChromium::rende
rPassMaskProgram() |
| 1503 { |
| 1504 if (!m_renderPassMaskProgram) |
| 1505 m_renderPassMaskProgram = adoptPtr(new RenderPassMaskProgram(m_context))
; |
| 1506 if (!m_renderPassMaskProgram->initialized()) { |
| 1507 TRACE_EVENT0("cc", "LayerRendererChromium::renderPassMaskProgram::initia
lize"); |
| 1508 m_renderPassMaskProgram->initialize(m_context); |
| 1509 } |
| 1510 return m_renderPassMaskProgram.get(); |
| 1511 } |
| 1512 |
| 1513 const LayerRendererChromium::RenderPassMaskProgramAA* LayerRendererChromium::ren
derPassMaskProgramAA() |
| 1514 { |
| 1515 if (!m_renderPassMaskProgramAA) |
| 1516 m_renderPassMaskProgramAA = adoptPtr(new RenderPassMaskProgramAA(m_conte
xt)); |
| 1517 if (!m_renderPassMaskProgramAA->initialized()) { |
| 1518 TRACE_EVENT0("cc", "LayerRendererChromium::renderPassMaskProgramAA::init
ialize"); |
| 1519 m_renderPassMaskProgramAA->initialize(m_context); |
| 1520 } |
| 1521 return m_renderPassMaskProgramAA.get(); |
| 1522 } |
| 1523 |
| 1524 const LayerRendererChromium::TileProgram* LayerRendererChromium::tileProgram() |
| 1525 { |
| 1526 ASSERT(m_tileProgram); |
| 1527 if (!m_tileProgram->initialized()) { |
| 1528 TRACE_EVENT0("cc", "LayerRendererChromium::tileProgram::initialize"); |
| 1529 m_tileProgram->initialize(m_context); |
| 1530 } |
| 1531 return m_tileProgram.get(); |
| 1532 } |
| 1533 |
| 1534 const LayerRendererChromium::TileProgramOpaque* LayerRendererChromium::tileProgr
amOpaque() |
| 1535 { |
| 1536 ASSERT(m_tileProgramOpaque); |
| 1537 if (!m_tileProgramOpaque->initialized()) { |
| 1538 TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramOpaque::initialize
"); |
| 1539 m_tileProgramOpaque->initialize(m_context); |
| 1540 } |
| 1541 return m_tileProgramOpaque.get(); |
| 1542 } |
| 1543 |
| 1544 const LayerRendererChromium::TileProgramAA* LayerRendererChromium::tileProgramAA
() |
| 1545 { |
| 1546 if (!m_tileProgramAA) |
| 1547 m_tileProgramAA = adoptPtr(new TileProgramAA(m_context)); |
| 1548 if (!m_tileProgramAA->initialized()) { |
| 1549 TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramAA::initialize"); |
| 1550 m_tileProgramAA->initialize(m_context); |
| 1551 } |
| 1552 return m_tileProgramAA.get(); |
| 1553 } |
| 1554 |
| 1555 const LayerRendererChromium::TileProgramSwizzle* LayerRendererChromium::tileProg
ramSwizzle() |
| 1556 { |
| 1557 if (!m_tileProgramSwizzle) |
| 1558 m_tileProgramSwizzle = adoptPtr(new TileProgramSwizzle(m_context)); |
| 1559 if (!m_tileProgramSwizzle->initialized()) { |
| 1560 TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramSwizzle::initializ
e"); |
| 1561 m_tileProgramSwizzle->initialize(m_context); |
| 1562 } |
| 1563 return m_tileProgramSwizzle.get(); |
| 1564 } |
| 1565 |
| 1566 const LayerRendererChromium::TileProgramSwizzleOpaque* LayerRendererChromium::ti
leProgramSwizzleOpaque() |
| 1567 { |
| 1568 if (!m_tileProgramSwizzleOpaque) |
| 1569 m_tileProgramSwizzleOpaque = adoptPtr(new TileProgramSwizzleOpaque(m_con
text)); |
| 1570 if (!m_tileProgramSwizzleOpaque->initialized()) { |
| 1571 TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramSwizzleOpaque::ini
tialize"); |
| 1572 m_tileProgramSwizzleOpaque->initialize(m_context); |
| 1573 } |
| 1574 return m_tileProgramSwizzleOpaque.get(); |
| 1575 } |
| 1576 |
| 1577 const LayerRendererChromium::TileProgramSwizzleAA* LayerRendererChromium::tilePr
ogramSwizzleAA() |
| 1578 { |
| 1579 if (!m_tileProgramSwizzleAA) |
| 1580 m_tileProgramSwizzleAA = adoptPtr(new TileProgramSwizzleAA(m_context)); |
| 1581 if (!m_tileProgramSwizzleAA->initialized()) { |
| 1582 TRACE_EVENT0("cc", "LayerRendererChromium::tileProgramSwizzleAA::initial
ize"); |
| 1583 m_tileProgramSwizzleAA->initialize(m_context); |
| 1584 } |
| 1585 return m_tileProgramSwizzleAA.get(); |
| 1586 } |
| 1587 |
| 1588 const LayerRendererChromium::TextureProgram* LayerRendererChromium::textureProgr
am() |
| 1589 { |
| 1590 if (!m_textureProgram) |
| 1591 m_textureProgram = adoptPtr(new TextureProgram(m_context)); |
| 1592 if (!m_textureProgram->initialized()) { |
| 1593 TRACE_EVENT0("cc", "LayerRendererChromium::textureProgram::initialize"); |
| 1594 m_textureProgram->initialize(m_context); |
| 1595 } |
| 1596 return m_textureProgram.get(); |
| 1597 } |
| 1598 |
| 1599 const LayerRendererChromium::TextureProgramFlip* LayerRendererChromium::textureP
rogramFlip() |
| 1600 { |
| 1601 if (!m_textureProgramFlip) |
| 1602 m_textureProgramFlip = adoptPtr(new TextureProgramFlip(m_context)); |
| 1603 if (!m_textureProgramFlip->initialized()) { |
| 1604 TRACE_EVENT0("cc", "LayerRendererChromium::textureProgramFlip::initializ
e"); |
| 1605 m_textureProgramFlip->initialize(m_context); |
| 1606 } |
| 1607 return m_textureProgramFlip.get(); |
| 1608 } |
| 1609 |
| 1610 const LayerRendererChromium::TextureIOSurfaceProgram* LayerRendererChromium::tex
tureIOSurfaceProgram() |
| 1611 { |
| 1612 if (!m_textureIOSurfaceProgram) |
| 1613 m_textureIOSurfaceProgram = adoptPtr(new TextureIOSurfaceProgram(m_conte
xt)); |
| 1614 if (!m_textureIOSurfaceProgram->initialized()) { |
| 1615 TRACE_EVENT0("cc", "LayerRendererChromium::textureIOSurfaceProgram::init
ialize"); |
| 1616 m_textureIOSurfaceProgram->initialize(m_context); |
| 1617 } |
| 1618 return m_textureIOSurfaceProgram.get(); |
| 1619 } |
| 1620 |
| 1621 const LayerRendererChromium::VideoYUVProgram* LayerRendererChromium::videoYUVPro
gram() |
| 1622 { |
| 1623 if (!m_videoYUVProgram) |
| 1624 m_videoYUVProgram = adoptPtr(new VideoYUVProgram(m_context)); |
| 1625 if (!m_videoYUVProgram->initialized()) { |
| 1626 TRACE_EVENT0("cc", "LayerRendererChromium::videoYUVProgram::initialize")
; |
| 1627 m_videoYUVProgram->initialize(m_context); |
| 1628 } |
| 1629 return m_videoYUVProgram.get(); |
| 1630 } |
| 1631 |
| 1632 const LayerRendererChromium::VideoStreamTextureProgram* LayerRendererChromium::v
ideoStreamTextureProgram() |
| 1633 { |
| 1634 if (!m_videoStreamTextureProgram) |
| 1635 m_videoStreamTextureProgram = adoptPtr(new VideoStreamTextureProgram(m_c
ontext)); |
| 1636 if (!m_videoStreamTextureProgram->initialized()) { |
| 1637 TRACE_EVENT0("cc", "LayerRendererChromium::streamTextureProgram::initial
ize"); |
| 1638 m_videoStreamTextureProgram->initialize(m_context); |
| 1639 } |
| 1640 return m_videoStreamTextureProgram.get(); |
| 1641 } |
| 1642 |
| 1643 void LayerRendererChromium::cleanupSharedObjects() |
| 1644 { |
| 1645 makeContextCurrent(); |
| 1646 |
| 1647 m_sharedGeometry.clear(); |
| 1648 |
| 1649 if (m_tileProgram) |
| 1650 m_tileProgram->cleanup(m_context); |
| 1651 if (m_tileProgramOpaque) |
| 1652 m_tileProgramOpaque->cleanup(m_context); |
| 1653 if (m_tileProgramSwizzle) |
| 1654 m_tileProgramSwizzle->cleanup(m_context); |
| 1655 if (m_tileProgramSwizzleOpaque) |
| 1656 m_tileProgramSwizzleOpaque->cleanup(m_context); |
| 1657 if (m_tileProgramAA) |
| 1658 m_tileProgramAA->cleanup(m_context); |
| 1659 if (m_tileProgramSwizzleAA) |
| 1660 m_tileProgramSwizzleAA->cleanup(m_context); |
| 1661 if (m_tileCheckerboardProgram) |
| 1662 m_tileCheckerboardProgram->cleanup(m_context); |
| 1663 |
| 1664 if (m_renderPassMaskProgram) |
| 1665 m_renderPassMaskProgram->cleanup(m_context); |
| 1666 if (m_renderPassProgram) |
| 1667 m_renderPassProgram->cleanup(m_context); |
| 1668 if (m_renderPassMaskProgramAA) |
| 1669 m_renderPassMaskProgramAA->cleanup(m_context); |
| 1670 if (m_renderPassProgramAA) |
| 1671 m_renderPassProgramAA->cleanup(m_context); |
| 1672 |
| 1673 if (m_textureProgram) |
| 1674 m_textureProgram->cleanup(m_context); |
| 1675 if (m_textureProgramFlip) |
| 1676 m_textureProgramFlip->cleanup(m_context); |
| 1677 if (m_textureIOSurfaceProgram) |
| 1678 m_textureIOSurfaceProgram->cleanup(m_context); |
| 1679 |
| 1680 if (m_videoYUVProgram) |
| 1681 m_videoYUVProgram->cleanup(m_context); |
| 1682 if (m_videoStreamTextureProgram) |
| 1683 m_videoStreamTextureProgram->cleanup(m_context); |
| 1684 |
| 1685 if (m_solidColorProgram) |
| 1686 m_solidColorProgram->cleanup(m_context); |
| 1687 |
| 1688 if (m_headsUpDisplayProgram) |
| 1689 m_headsUpDisplayProgram->cleanup(m_context); |
| 1690 |
| 1691 if (m_offscreenFramebufferId) |
| 1692 GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId)); |
| 1693 |
| 1694 m_textureCopier.clear(); |
| 1695 m_textureUploader.clear(); |
| 1696 |
| 1697 releaseRenderPassTextures(); |
| 1698 } |
| 1699 |
| 1700 bool LayerRendererChromium::isContextLost() |
| 1701 { |
| 1702 return (m_context->getGraphicsResetStatusARB() != GL_NO_ERROR); |
| 1703 } |
| 1704 |
| 1705 } // namespace WebCore |
| 1706 |
| 1707 #endif // USE(ACCELERATED_COMPOSITING) |
OLD | NEW |