| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2012 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 "config.h" |
| 6 #include "CCRendererGL.h" |
| 7 |
| 8 #include "CCDrawQuad.h" |
| 9 #include "CCPrioritizedTextureManager.h" |
| 10 #include "CCResourceProvider.h" |
| 11 #include "CCSettings.h" |
| 12 #include "CCSingleThreadProxy.h" |
| 13 #include "CCTestCommon.h" |
| 14 #include "FakeWebCompositorOutputSurface.h" |
| 15 #include "FakeWebGraphicsContext3D.h" |
| 16 #include "GraphicsContext3D.h" |
| 17 #include "WebCompositorInitializer.h" |
| 18 #include <gmock/gmock.h> |
| 19 #include <gtest/gtest.h> |
| 20 #include <public/WebTransformationMatrix.h> |
| 21 |
| 22 using namespace cc; |
| 23 using namespace WebKit; |
| 24 using namespace WebKitTests; |
| 25 |
| 26 class FrameCountingMemoryAllocationSettingContext : public FakeWebGraphicsContex
t3D { |
| 27 public: |
| 28 FrameCountingMemoryAllocationSettingContext() : m_frame(0) { } |
| 29 |
| 30 // WebGraphicsContext3D methods. |
| 31 |
| 32 // This method would normally do a glSwapBuffers under the hood. |
| 33 virtual void prepareTexture() { m_frame++; } |
| 34 virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAll
ocationChangedCallbackCHROMIUM* callback) { m_memoryAllocationChangedCallback =
callback; } |
| 35 virtual WebString getString(WebKit::WGC3Denum name) |
| 36 { |
| 37 if (name == GraphicsContext3D::EXTENSIONS) |
| 38 return WebString("GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_
manager GL_CHROMIUM_discard_framebuffer"); |
| 39 return WebString(); |
| 40 } |
| 41 |
| 42 // Methods added for test. |
| 43 int frameCount() { return m_frame; } |
| 44 void setMemoryAllocation(WebGraphicsMemoryAllocation allocation) |
| 45 { |
| 46 ASSERT(CCProxy::isImplThread()); |
| 47 // In single threaded mode we expect this callback on main thread. |
| 48 DebugScopedSetMainThread main; |
| 49 m_memoryAllocationChangedCallback->onMemoryAllocationChanged(allocation)
; |
| 50 } |
| 51 |
| 52 private: |
| 53 int m_frame; |
| 54 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* m_memoryAllocationChange
dCallback; |
| 55 }; |
| 56 |
| 57 class FakeCCRendererClient : public CCRendererClient { |
| 58 public: |
| 59 FakeCCRendererClient() |
| 60 : m_setFullRootLayerDamageCount(0) |
| 61 , m_rootLayer(CCLayerImpl::create(1)) |
| 62 , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemor
yAllocationLimit()) |
| 63 { |
| 64 m_rootLayer->createRenderSurface(); |
| 65 CCRenderPass::Id renderPassId = m_rootLayer->renderSurface()->renderPass
Id(); |
| 66 OwnPtr<CCRenderPass> rootRenderPass = CCRenderPass::create(renderPassId,
IntRect(), WebTransformationMatrix()); |
| 67 m_renderPassesInDrawOrder.append(rootRenderPass.get()); |
| 68 m_renderPasses.set(renderPassId, rootRenderPass.release()); |
| 69 } |
| 70 |
| 71 // CCRendererClient methods. |
| 72 virtual const IntSize& deviceViewportSize() const OVERRIDE { static IntSize
fakeSize(1, 1); return fakeSize; } |
| 73 virtual const CCLayerTreeSettings& settings() const OVERRIDE { static CCLaye
rTreeSettings fakeSettings; return fakeSettings; } |
| 74 virtual void didLoseContext() OVERRIDE { } |
| 75 virtual void onSwapBuffersComplete() OVERRIDE { } |
| 76 virtual void setFullRootLayerDamage() OVERRIDE { m_setFullRootLayerDamageCou
nt++; } |
| 77 virtual void releaseContentsTextures() OVERRIDE { } |
| 78 virtual void setMemoryAllocationLimitBytes(size_t bytes) OVERRIDE { m_memory
AllocationLimitBytes = bytes; } |
| 79 |
| 80 // Methods added for test. |
| 81 int setFullRootLayerDamageCount() const { return m_setFullRootLayerDamageCou
nt; } |
| 82 |
| 83 CCRenderPass* rootRenderPass() { return m_renderPassesInDrawOrder.last(); } |
| 84 const CCRenderPassList& renderPassesInDrawOrder() const { return m_renderPas
sesInDrawOrder; } |
| 85 const CCRenderPassIdHashMap& renderPasses() const { return m_renderPasses; } |
| 86 |
| 87 size_t memoryAllocationLimitBytes() const { return m_memoryAllocationLimitBy
tes; } |
| 88 |
| 89 private: |
| 90 int m_setFullRootLayerDamageCount; |
| 91 DebugScopedSetImplThread m_implThread; |
| 92 OwnPtr<CCLayerImpl> m_rootLayer; |
| 93 CCRenderPassList m_renderPassesInDrawOrder; |
| 94 CCRenderPassIdHashMap m_renderPasses; |
| 95 size_t m_memoryAllocationLimitBytes; |
| 96 }; |
| 97 |
| 98 class FakeCCRendererGL : public CCRendererGL { |
| 99 public: |
| 100 FakeCCRendererGL(CCRendererClient* client, CCResourceProvider* resourceProvi
der) : CCRendererGL(client, resourceProvider) { } |
| 101 |
| 102 // CCRendererGL methods. |
| 103 |
| 104 // Changing visibility to public. |
| 105 using CCRendererGL::initialize; |
| 106 using CCRendererGL::isFramebufferDiscarded; |
| 107 }; |
| 108 |
| 109 class CCRendererGLTest : public testing::Test { |
| 110 protected: |
| 111 CCRendererGLTest() |
| 112 : m_suggestHaveBackbufferYes(1, true) |
| 113 , m_suggestHaveBackbufferNo(1, false) |
| 114 , m_compositorInitializer(0) |
| 115 , m_context(FakeWebCompositorOutputSurface::create(adoptPtr(new FrameCou
ntingMemoryAllocationSettingContext()))) |
| 116 , m_resourceProvider(CCResourceProvider::create(m_context.get(), Unthrot
tledUploader)) |
| 117 , m_renderer(&m_mockClient, m_resourceProvider.get()) |
| 118 { |
| 119 } |
| 120 |
| 121 virtual void SetUp() |
| 122 { |
| 123 m_renderer.initialize(); |
| 124 } |
| 125 |
| 126 void swapBuffers() |
| 127 { |
| 128 m_renderer.swapBuffers(); |
| 129 } |
| 130 |
| 131 FrameCountingMemoryAllocationSettingContext* context() { return static_cast<
FrameCountingMemoryAllocationSettingContext*>(m_context->context3D()); } |
| 132 |
| 133 WebGraphicsMemoryAllocation m_suggestHaveBackbufferYes; |
| 134 WebGraphicsMemoryAllocation m_suggestHaveBackbufferNo; |
| 135 |
| 136 WebCompositorInitializer m_compositorInitializer; |
| 137 OwnPtr<CCGraphicsContext> m_context; |
| 138 FakeCCRendererClient m_mockClient; |
| 139 OwnPtr<CCResourceProvider> m_resourceProvider; |
| 140 FakeCCRendererGL m_renderer; |
| 141 CCScopedSettings m_scopedSettings; |
| 142 }; |
| 143 |
| 144 // Test CCRendererGL discardFramebuffer functionality: |
| 145 // Suggest recreating framebuffer when one already exists. |
| 146 // Expected: it does nothing. |
| 147 TEST_F(CCRendererGLTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing) |
| 148 { |
| 149 context()->setMemoryAllocation(m_suggestHaveBackbufferYes); |
| 150 EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount()); |
| 151 EXPECT_FALSE(m_renderer.isFramebufferDiscarded()); |
| 152 |
| 153 swapBuffers(); |
| 154 EXPECT_EQ(1, context()->frameCount()); |
| 155 } |
| 156 |
| 157 // Test CCRendererGL discardFramebuffer functionality: |
| 158 // Suggest discarding framebuffer when one exists and the renderer is not visibl
e. |
| 159 // Expected: it is discarded and damage tracker is reset. |
| 160 TEST_F(CCRendererGLTest, SuggestBackbufferNoShouldDiscardBackbufferAndDamageRoot
LayerWhileNotVisible) |
| 161 { |
| 162 m_renderer.setVisible(false); |
| 163 context()->setMemoryAllocation(m_suggestHaveBackbufferNo); |
| 164 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount()); |
| 165 EXPECT_TRUE(m_renderer.isFramebufferDiscarded()); |
| 166 } |
| 167 |
| 168 // Test CCRendererGL discardFramebuffer functionality: |
| 169 // Suggest discarding framebuffer when one exists and the renderer is visible. |
| 170 // Expected: the allocation is ignored. |
| 171 TEST_F(CCRendererGLTest, SuggestBackbufferNoDoNothingWhenVisible) |
| 172 { |
| 173 m_renderer.setVisible(true); |
| 174 context()->setMemoryAllocation(m_suggestHaveBackbufferNo); |
| 175 EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount()); |
| 176 EXPECT_FALSE(m_renderer.isFramebufferDiscarded()); |
| 177 } |
| 178 |
| 179 |
| 180 // Test CCRendererGL discardFramebuffer functionality: |
| 181 // Suggest discarding framebuffer when one does not exist. |
| 182 // Expected: it does nothing. |
| 183 TEST_F(CCRendererGLTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) |
| 184 { |
| 185 m_renderer.setVisible(false); |
| 186 context()->setMemoryAllocation(m_suggestHaveBackbufferNo); |
| 187 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount()); |
| 188 EXPECT_TRUE(m_renderer.isFramebufferDiscarded()); |
| 189 |
| 190 context()->setMemoryAllocation(m_suggestHaveBackbufferNo); |
| 191 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount()); |
| 192 EXPECT_TRUE(m_renderer.isFramebufferDiscarded()); |
| 193 } |
| 194 |
| 195 // Test CCRendererGL discardFramebuffer functionality: |
| 196 // Begin drawing a frame while a framebuffer is discarded. |
| 197 // Expected: will recreate framebuffer. |
| 198 TEST_F(CCRendererGLTest, DiscardedBackbufferIsRecreatedForScopeDuration) |
| 199 { |
| 200 m_renderer.setVisible(false); |
| 201 context()->setMemoryAllocation(m_suggestHaveBackbufferNo); |
| 202 EXPECT_TRUE(m_renderer.isFramebufferDiscarded()); |
| 203 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount()); |
| 204 |
| 205 m_renderer.setVisible(true); |
| 206 m_renderer.drawFrame(m_mockClient.renderPassesInDrawOrder(), m_mockClient.re
nderPasses()); |
| 207 EXPECT_FALSE(m_renderer.isFramebufferDiscarded()); |
| 208 |
| 209 swapBuffers(); |
| 210 EXPECT_EQ(1, context()->frameCount()); |
| 211 } |
| 212 |
| 213 TEST_F(CCRendererGLTest, FramebufferDiscardedAfterReadbackWhenNotVisible) |
| 214 { |
| 215 m_renderer.setVisible(false); |
| 216 context()->setMemoryAllocation(m_suggestHaveBackbufferNo); |
| 217 EXPECT_TRUE(m_renderer.isFramebufferDiscarded()); |
| 218 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount()); |
| 219 |
| 220 char pixels[4]; |
| 221 m_renderer.drawFrame(m_mockClient.renderPassesInDrawOrder(), m_mockClient.re
nderPasses()); |
| 222 EXPECT_FALSE(m_renderer.isFramebufferDiscarded()); |
| 223 |
| 224 m_renderer.getFramebufferPixels(pixels, IntRect(0, 0, 1, 1)); |
| 225 EXPECT_TRUE(m_renderer.isFramebufferDiscarded()); |
| 226 EXPECT_EQ(2, m_mockClient.setFullRootLayerDamageCount()); |
| 227 } |
| 228 |
| 229 class ForbidSynchronousCallContext : public FakeWebGraphicsContext3D { |
| 230 public: |
| 231 ForbidSynchronousCallContext() { } |
| 232 |
| 233 virtual bool getActiveAttrib(WebGLId program, WGC3Duint index, ActiveInfo&)
{ ADD_FAILURE(); return false; } |
| 234 virtual bool getActiveUniform(WebGLId program, WGC3Duint index, ActiveInfo&)
{ ADD_FAILURE(); return false; } |
| 235 virtual void getAttachedShaders(WebGLId program, WGC3Dsizei maxCount, WGC3Ds
izei* count, WebGLId* shaders) { ADD_FAILURE(); } |
| 236 virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name) {
ADD_FAILURE(); return 0; } |
| 237 virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value) { ADD_FAILURE
(); } |
| 238 virtual void getBufferParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Din
t* value) { ADD_FAILURE(); } |
| 239 virtual Attributes getContextAttributes() { ADD_FAILURE(); return m_attrs; } |
| 240 virtual WGC3Denum getError() { ADD_FAILURE(); return 0; } |
| 241 virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE();
} |
| 242 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target, WGC3Denum
attachment, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); } |
| 243 virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value) |
| 244 { |
| 245 if (pname == GraphicsContext3D::MAX_TEXTURE_SIZE) |
| 246 *value = 1024; // MAX_TEXTURE_SIZE is cached client side, so it's OK
to query. |
| 247 else |
| 248 ADD_FAILURE(); |
| 249 } |
| 250 |
| 251 // We allow querying the shader compilation and program link status in debug
mode, but not release. |
| 252 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value) |
| 253 { |
| 254 #ifndef NDEBUG |
| 255 *value = 1; |
| 256 #else |
| 257 ADD_FAILURE(); |
| 258 #endif |
| 259 } |
| 260 |
| 261 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) |
| 262 { |
| 263 #ifndef NDEBUG |
| 264 *value = 1; |
| 265 #else |
| 266 ADD_FAILURE(); |
| 267 #endif |
| 268 } |
| 269 |
| 270 virtual WebString getString(WGC3Denum name) |
| 271 { |
| 272 // We allow querying the extension string. |
| 273 // FIXME: It'd be better to check that we only do this before starting a
ny other expensive work (like starting a compilation) |
| 274 if (name != GraphicsContext3D::EXTENSIONS) |
| 275 ADD_FAILURE(); |
| 276 return WebString(); |
| 277 } |
| 278 |
| 279 virtual WebString getProgramInfoLog(WebGLId program) { ADD_FAILURE(); return
WebString(); } |
| 280 virtual void getRenderbufferParameteriv(WGC3Denum target, WGC3Denum pname, W
GC3Dint* value) { ADD_FAILURE(); } |
| 281 |
| 282 virtual WebString getShaderInfoLog(WebGLId shader) { ADD_FAILURE(); return W
ebString(); } |
| 283 virtual void getShaderPrecisionFormat(WGC3Denum shadertype, WGC3Denum precis
iontype, WGC3Dint* range, WGC3Dint* precision) { ADD_FAILURE(); } |
| 284 virtual WebString getShaderSource(WebGLId shader) { ADD_FAILURE(); return We
bString(); } |
| 285 virtual void getTexParameterfv(WGC3Denum target, WGC3Denum pname, WGC3Dfloat
* value) { ADD_FAILURE(); } |
| 286 virtual void getTexParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint*
value) { ADD_FAILURE(); } |
| 287 virtual void getUniformfv(WebGLId program, WGC3Dint location, WGC3Dfloat* va
lue) { ADD_FAILURE(); } |
| 288 virtual void getUniformiv(WebGLId program, WGC3Dint location, WGC3Dint* valu
e) { ADD_FAILURE(); } |
| 289 virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name)
{ ADD_FAILURE(); return 0; } |
| 290 virtual void getVertexAttribfv(WGC3Duint index, WGC3Denum pname, WGC3Dfloat*
value) { ADD_FAILURE(); } |
| 291 virtual void getVertexAttribiv(WGC3Duint index, WGC3Denum pname, WGC3Dint* v
alue) { ADD_FAILURE(); } |
| 292 virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index, WGC3Denum pname
) { ADD_FAILURE(); return 0; } |
| 293 }; |
| 294 |
| 295 // This test isn't using the same fixture as CCRendererGLTest, and you can't mix
TEST() and TEST_F() with the same name, hence LRC2. |
| 296 TEST(CCRendererGLTest2, initializationDoesNotMakeSynchronousCalls) |
| 297 { |
| 298 CCScopedSettings scopedSettings; |
| 299 FakeCCRendererClient mockClient; |
| 300 OwnPtr<CCGraphicsContext> context(FakeWebCompositorOutputSurface::create(ado
ptPtr(new ForbidSynchronousCallContext))); |
| 301 OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(conte
xt.get(), UnthrottledUploader)); |
| 302 FakeCCRendererGL renderer(&mockClient, resourceProvider.get()); |
| 303 |
| 304 EXPECT_TRUE(renderer.initialize()); |
| 305 } |
| 306 |
| 307 class LoseContextOnFirstGetContext : public FakeWebGraphicsContext3D { |
| 308 public: |
| 309 LoseContextOnFirstGetContext() |
| 310 : m_contextLost(false) |
| 311 { |
| 312 } |
| 313 |
| 314 virtual bool makeContextCurrent() OVERRIDE |
| 315 { |
| 316 return !m_contextLost; |
| 317 } |
| 318 |
| 319 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
OVERRIDE |
| 320 { |
| 321 m_contextLost = true; |
| 322 *value = 0; |
| 323 } |
| 324 |
| 325 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) O
VERRIDE |
| 326 { |
| 327 m_contextLost = true; |
| 328 *value = 0; |
| 329 } |
| 330 |
| 331 virtual WGC3Denum getGraphicsResetStatusARB() OVERRIDE |
| 332 { |
| 333 return m_contextLost ? 1 : 0; |
| 334 } |
| 335 |
| 336 private: |
| 337 bool m_contextLost; |
| 338 }; |
| 339 |
| 340 TEST(CCRendererGLTest2, initializationWithQuicklyLostContextDoesNotAssert) |
| 341 { |
| 342 CCScopedSettings scopedSettings; |
| 343 FakeCCRendererClient mockClient; |
| 344 OwnPtr<CCGraphicsContext> context(FakeWebCompositorOutputSurface::create(ado
ptPtr(new LoseContextOnFirstGetContext))); |
| 345 OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(conte
xt.get(), UnthrottledUploader)); |
| 346 FakeCCRendererGL renderer(&mockClient, resourceProvider.get()); |
| 347 |
| 348 renderer.initialize(); |
| 349 } |
| 350 |
| 351 class ContextThatDoesNotSupportMemoryManagmentExtensions : public FakeWebGraphic
sContext3D { |
| 352 public: |
| 353 ContextThatDoesNotSupportMemoryManagmentExtensions() { } |
| 354 |
| 355 // WebGraphicsContext3D methods. |
| 356 |
| 357 // This method would normally do a glSwapBuffers under the hood. |
| 358 virtual void prepareTexture() { } |
| 359 virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAll
ocationChangedCallbackCHROMIUM* callback) { } |
| 360 virtual WebString getString(WebKit::WGC3Denum name) { return WebString(); } |
| 361 }; |
| 362 |
| 363 TEST(CCRendererGLTest2, initializationWithoutGpuMemoryManagerExtensionSupportSho
uldDefaultToNonZeroAllocation) |
| 364 { |
| 365 FakeCCRendererClient mockClient; |
| 366 OwnPtr<CCGraphicsContext> context(FakeWebCompositorOutputSurface::create(ado
ptPtr(new ContextThatDoesNotSupportMemoryManagmentExtensions))); |
| 367 OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(conte
xt.get(), UnthrottledUploader)); |
| 368 FakeCCRendererGL renderer(&mockClient, resourceProvider.get()); |
| 369 |
| 370 renderer.initialize(); |
| 371 |
| 372 EXPECT_GT(mockClient.memoryAllocationLimitBytes(), 0ul); |
| 373 } |
| 374 |
| 375 class ClearCountingContext : public FakeWebGraphicsContext3D { |
| 376 public: |
| 377 ClearCountingContext() : m_clear(0) { } |
| 378 |
| 379 virtual void clear(WGC3Dbitfield) |
| 380 { |
| 381 m_clear++; |
| 382 } |
| 383 |
| 384 int clearCount() const { return m_clear; } |
| 385 |
| 386 private: |
| 387 int m_clear; |
| 388 }; |
| 389 |
| 390 TEST(CCRendererGLTest2, opaqueBackground) |
| 391 { |
| 392 FakeCCRendererClient mockClient; |
| 393 OwnPtr<CCGraphicsContext> ccContext(FakeWebCompositorOutputSurface::create(a
doptPtr(new ClearCountingContext))); |
| 394 ClearCountingContext* context = static_cast<ClearCountingContext*>(ccContext
->context3D()); |
| 395 OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(ccCon
text.get(), UnthrottledUploader)); |
| 396 FakeCCRendererGL renderer(&mockClient, resourceProvider.get()); |
| 397 |
| 398 mockClient.rootRenderPass()->setHasTransparentBackground(false); |
| 399 |
| 400 EXPECT_TRUE(renderer.initialize()); |
| 401 |
| 402 renderer.drawFrame(mockClient.renderPassesInDrawOrder(), mockClient.renderPa
sses()); |
| 403 |
| 404 // On DEBUG builds, render passes with opaque background clear to blue to |
| 405 // easily see regions that were not drawn on the screen. |
| 406 #if defined(NDEBUG) |
| 407 EXPECT_EQ(0, context->clearCount()); |
| 408 #else |
| 409 EXPECT_EQ(1, context->clearCount()); |
| 410 #endif |
| 411 } |
| 412 |
| 413 TEST(CCRendererGLTest2, transparentBackground) |
| 414 { |
| 415 FakeCCRendererClient mockClient; |
| 416 OwnPtr<CCGraphicsContext> ccContext(FakeWebCompositorOutputSurface::create(a
doptPtr(new ClearCountingContext))); |
| 417 ClearCountingContext* context = static_cast<ClearCountingContext*>(ccContext
->context3D()); |
| 418 OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(ccCon
text.get(), UnthrottledUploader)); |
| 419 FakeCCRendererGL renderer(&mockClient, resourceProvider.get()); |
| 420 |
| 421 mockClient.rootRenderPass()->setHasTransparentBackground(true); |
| 422 |
| 423 EXPECT_TRUE(renderer.initialize()); |
| 424 |
| 425 renderer.drawFrame(mockClient.renderPassesInDrawOrder(), mockClient.renderPa
sses()); |
| 426 |
| 427 EXPECT_EQ(1, context->clearCount()); |
| 428 } |
| OLD | NEW |