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.
7 #include "CCDirectRenderer.h"
9 #include "CCMathUtil.h"
10 #include <public/WebTransformationMatrix.h>
13 using WebKit::WebTransformationMatrix
;
15 static WebTransformationMatrix
orthoProjectionMatrix(float left
, float right
, float bottom
, float top
)
17 // Use the standard formula to map the clipping frustum to the cube from
18 // [-1, -1, -1] to [1, 1, 1].
19 float deltaX
= right
- left
;
20 float deltaY
= top
- bottom
;
21 WebTransformationMatrix proj
;
22 if (!deltaX
|| !deltaY
)
24 proj
.setM11(2.0f
/ deltaX
);
25 proj
.setM41(-(right
+ left
) / deltaX
);
26 proj
.setM22(2.0f
/ deltaY
);
27 proj
.setM42(-(top
+ bottom
) / deltaY
);
29 // Z component of vertices is always set to zero as we don't use the depth buffer
36 static WebTransformationMatrix
windowMatrix(int x
, int y
, int width
, int height
)
38 WebTransformationMatrix canvas
;
40 // Map to window position and scale up to pixel coordinates.
41 canvas
.translate3d(x
, y
, 0);
42 canvas
.scale3d(width
, height
, 0);
44 // Map from ([-1, -1] to [1, 1]) -> ([0, 0] to [1, 1])
45 canvas
.translate3d(0.5, 0.5, 0.5);
46 canvas
.scale3d(0.5, 0.5, 0.5);
53 CCDirectRenderer::DrawingFrame::DrawingFrame()
55 , currentRenderPass(0)
61 CCDirectRenderer::DrawingFrame::~DrawingFrame()
67 FloatRect
CCDirectRenderer::quadVertexRect()
69 return FloatRect(-0.5, -0.5, 1, 1);
73 void CCDirectRenderer::quadRectTransform(WebKit::WebTransformationMatrix
* quadRectTransform
, const WebKit::WebTransformationMatrix
& quadTransform
, const FloatRect
& quadRect
)
75 *quadRectTransform
= quadTransform
;
76 quadRectTransform
->translate(0.5 * quadRect
.width() + quadRect
.x(), 0.5 * quadRect
.height() + quadRect
.y());
77 quadRectTransform
->scaleNonUniform(quadRect
.width(), quadRect
.height());
81 void CCDirectRenderer::initializeMatrices(DrawingFrame
& frame
, const IntRect
& drawRect
, bool flipY
)
84 frame
.projectionMatrix
= orthoProjectionMatrix(drawRect
.x(), drawRect
.maxX(), drawRect
.maxY(), drawRect
.y());
86 frame
.projectionMatrix
= orthoProjectionMatrix(drawRect
.x(), drawRect
.maxX(), drawRect
.y(), drawRect
.maxY());
87 frame
.windowMatrix
= windowMatrix(0, 0, drawRect
.width(), drawRect
.height());
88 frame
.flippedY
= flipY
;
92 IntRect
CCDirectRenderer::moveScissorToWindowSpace(const DrawingFrame
& frame
, FloatRect scissorRect
)
94 IntRect scissorRectInCanvasSpace
= enclosingIntRect(scissorRect
);
95 // The scissor coordinates must be supplied in viewport space so we need to offset
96 // by the relative position of the top left corner of the current render pass.
97 IntRect framebufferOutputRect
= frame
.currentRenderPass
->outputRect();
98 scissorRectInCanvasSpace
.setX(scissorRectInCanvasSpace
.x() - framebufferOutputRect
.x());
99 if (frame
.flippedY
&& !frame
.currentTexture
)
100 scissorRectInCanvasSpace
.setY(framebufferOutputRect
.height() - (scissorRectInCanvasSpace
.maxY() - framebufferOutputRect
.y()));
102 scissorRectInCanvasSpace
.setY(scissorRectInCanvasSpace
.y() - framebufferOutputRect
.y());
103 return scissorRectInCanvasSpace
;
106 CCDirectRenderer::CCDirectRenderer(CCRendererClient
* client
, CCResourceProvider
* resourceProvider
)
108 , m_resourceProvider(resourceProvider
)
112 CCDirectRenderer::~CCDirectRenderer()
116 void CCDirectRenderer::decideRenderPassAllocationsForFrame(const CCRenderPassList
& renderPassesInDrawOrder
)
118 base::hash_map
<CCRenderPass::Id
, const CCRenderPass
*> renderPassesInFrame
;
119 for (size_t i
= 0; i
< renderPassesInDrawOrder
.size(); ++i
)
120 renderPassesInFrame
.insert(std::pair
<CCRenderPass::Id
, const CCRenderPass
*>(renderPassesInDrawOrder
[i
]->id(), renderPassesInDrawOrder
[i
]));
122 std::vector
<CCRenderPass::Id
> passesToDelete
;
123 ScopedPtrHashMap
<CCRenderPass::Id
, CachedTexture
>::const_iterator passIterator
;
124 for (passIterator
= m_renderPassTextures
.begin(); passIterator
!= m_renderPassTextures
.end(); ++passIterator
) {
125 base::hash_map
<CCRenderPass::Id
, const CCRenderPass
*>::const_iterator it
= renderPassesInFrame
.find(passIterator
->first
);
126 if (it
== renderPassesInFrame
.end()) {
127 passesToDelete
.push_back(passIterator
->first
);
131 const CCRenderPass
* renderPassInFrame
= it
->second
;
132 const IntSize
& requiredSize
= renderPassTextureSize(renderPassInFrame
);
133 GC3Denum requiredFormat
= renderPassTextureFormat(renderPassInFrame
);
134 CachedTexture
* texture
= passIterator
->second
;
137 if (texture
->id() && (texture
->size() != requiredSize
|| texture
->format() != requiredFormat
))
141 // Delete RenderPass textures from the previous frame that will not be used again.
142 for (size_t i
= 0; i
< passesToDelete
.size(); ++i
)
143 m_renderPassTextures
.erase(passesToDelete
[i
]);
145 for (size_t i
= 0; i
< renderPassesInDrawOrder
.size(); ++i
) {
146 if (!m_renderPassTextures
.contains(renderPassesInDrawOrder
[i
]->id())) {
147 scoped_ptr
<CachedTexture
> texture
= CachedTexture::create(m_resourceProvider
);
148 m_renderPassTextures
.set(renderPassesInDrawOrder
[i
]->id(), texture
.Pass());
153 void CCDirectRenderer::drawFrame(const CCRenderPassList
& renderPassesInDrawOrder
, const CCRenderPassIdHashMap
& renderPassesById
)
155 const CCRenderPass
* rootRenderPass
= renderPassesInDrawOrder
.back();
156 ASSERT(rootRenderPass
);
159 frame
.renderPassesById
= &renderPassesById
;
160 frame
.rootRenderPass
= rootRenderPass
;
161 frame
.rootDamageRect
= capabilities().usingPartialSwap
? rootRenderPass
->damageRect() : rootRenderPass
->outputRect();
162 frame
.rootDamageRect
.intersect(IntRect(IntPoint::zero(), viewportSize()));
164 beginDrawingFrame(frame
);
165 for (size_t i
= 0; i
< renderPassesInDrawOrder
.size(); ++i
)
166 drawRenderPass(frame
, renderPassesInDrawOrder
[i
]);
167 finishDrawingFrame(frame
);
170 void CCDirectRenderer::drawRenderPass(DrawingFrame
& frame
, const CCRenderPass
* renderPass
)
172 if (!useRenderPass(frame
, renderPass
))
175 frame
.scissorRectInRenderPassSpace
= frame
.currentRenderPass
->outputRect();
176 if (frame
.rootDamageRect
!= frame
.rootRenderPass
->outputRect()) {
177 WebTransformationMatrix inverseTransformToRoot
= frame
.currentRenderPass
->transformToRootTarget().inverse();
178 frame
.scissorRectInRenderPassSpace
.intersect(CCMathUtil::projectClippedRect(inverseTransformToRoot
, frame
.rootDamageRect
));
181 enableScissorTestRect(moveScissorToWindowSpace(frame
, frame
.scissorRectInRenderPassSpace
));
182 clearFramebuffer(frame
);
184 const CCQuadList
& quadList
= renderPass
->quadList();
185 for (CCQuadList::constBackToFrontIterator it
= quadList
.backToFrontBegin(); it
!= quadList
.backToFrontEnd(); ++it
) {
186 FloatRect quadScissorRect
= frame
.scissorRectInRenderPassSpace
;
187 quadScissorRect
.intersect((*it
)->clippedRectInTarget());
188 if (!quadScissorRect
.isEmpty()) {
189 enableScissorTestRect(moveScissorToWindowSpace(frame
, quadScissorRect
));
190 drawQuad(frame
, *it
);
194 CachedTexture
* texture
= m_renderPassTextures
.get(renderPass
->id());
196 texture
->setIsComplete(!renderPass
->hasOcclusionFromOutsideTargetSurface());
199 bool CCDirectRenderer::useRenderPass(DrawingFrame
& frame
, const CCRenderPass
* renderPass
)
201 frame
.currentRenderPass
= renderPass
;
202 frame
.currentTexture
= 0;
204 if (renderPass
== frame
.rootRenderPass
) {
205 bindFramebufferToOutputSurface(frame
);
206 initializeMatrices(frame
, renderPass
->outputRect(), flippedFramebuffer());
207 setDrawViewportSize(renderPass
->outputRect().size());
211 CachedTexture
* texture
= m_renderPassTextures
.get(renderPass
->id());
213 if (!texture
->id() && !texture
->allocate(CCRenderer::ImplPool
, renderPassTextureSize(renderPass
), renderPassTextureFormat(renderPass
), CCResourceProvider::TextureUsageFramebuffer
))
216 return bindFramebufferToTexture(frame
, texture
, renderPass
->outputRect());
219 bool CCDirectRenderer::haveCachedResourcesForRenderPassId(CCRenderPass::Id id
) const
221 CachedTexture
* texture
= m_renderPassTextures
.get(id
);
222 return texture
&& texture
->id() && texture
->isComplete();
226 IntSize
CCDirectRenderer::renderPassTextureSize(const CCRenderPass
* pass
)
228 return pass
->outputRect().size();
232 GC3Denum
CCDirectRenderer::renderPassTextureFormat(const CCRenderPass
*)
234 return GraphicsContext3D::RGBA
;