| 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 | |
| 7 #include "CCDirectRenderer.h" | |
| 8 | |
| 9 #include "CCMathUtil.h" | |
| 10 #include <public/WebTransformationMatrix.h> | |
| 11 #include <vector> | |
| 12 | |
| 13 using WebKit::WebTransformationMatrix; | |
| 14 | |
| 15 static WebTransformationMatrix orthoProjectionMatrix(float left, float right, fl
oat bottom, float top) | |
| 16 { | |
| 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) | |
| 23 return proj; | |
| 24 proj.setM11(2.0f / deltaX); | |
| 25 proj.setM41(-(right + left) / deltaX); | |
| 26 proj.setM22(2.0f / deltaY); | |
| 27 proj.setM42(-(top + bottom) / deltaY); | |
| 28 | |
| 29 // Z component of vertices is always set to zero as we don't use the depth b
uffer | |
| 30 // while drawing. | |
| 31 proj.setM33(0); | |
| 32 | |
| 33 return proj; | |
| 34 } | |
| 35 | |
| 36 static WebTransformationMatrix windowMatrix(int x, int y, int width, int height) | |
| 37 { | |
| 38 WebTransformationMatrix canvas; | |
| 39 | |
| 40 // Map to window position and scale up to pixel coordinates. | |
| 41 canvas.translate3d(x, y, 0); | |
| 42 canvas.scale3d(width, height, 0); | |
| 43 | |
| 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); | |
| 47 | |
| 48 return canvas; | |
| 49 } | |
| 50 | |
| 51 namespace cc { | |
| 52 | |
| 53 CCDirectRenderer::DrawingFrame::DrawingFrame() | |
| 54 : rootRenderPass(0) | |
| 55 , currentRenderPass(0) | |
| 56 , currentTexture(0) | |
| 57 , flippedY(false) | |
| 58 { | |
| 59 } | |
| 60 | |
| 61 CCDirectRenderer::DrawingFrame::~DrawingFrame() | |
| 62 { | |
| 63 } | |
| 64 | |
| 65 // | |
| 66 // static | |
| 67 FloatRect CCDirectRenderer::quadVertexRect() | |
| 68 { | |
| 69 return FloatRect(-0.5, -0.5, 1, 1); | |
| 70 } | |
| 71 | |
| 72 // static | |
| 73 void CCDirectRenderer::quadRectTransform(WebKit::WebTransformationMatrix* quadRe
ctTransform, const WebKit::WebTransformationMatrix& quadTransform, const FloatRe
ct& quadRect) | |
| 74 { | |
| 75 *quadRectTransform = quadTransform; | |
| 76 quadRectTransform->translate(0.5 * quadRect.width() + quadRect.x(), 0.5 * qu
adRect.height() + quadRect.y()); | |
| 77 quadRectTransform->scaleNonUniform(quadRect.width(), quadRect.height()); | |
| 78 } | |
| 79 | |
| 80 // static | |
| 81 void CCDirectRenderer::initializeMatrices(DrawingFrame& frame, const IntRect& dr
awRect, bool flipY) | |
| 82 { | |
| 83 if (flipY) | |
| 84 frame.projectionMatrix = orthoProjectionMatrix(drawRect.x(), drawRect.ma
xX(), drawRect.maxY(), drawRect.y()); | |
| 85 else | |
| 86 frame.projectionMatrix = orthoProjectionMatrix(drawRect.x(), drawRect.ma
xX(), drawRect.y(), drawRect.maxY()); | |
| 87 frame.windowMatrix = windowMatrix(0, 0, drawRect.width(), drawRect.height())
; | |
| 88 frame.flippedY = flipY; | |
| 89 } | |
| 90 | |
| 91 // static | |
| 92 IntRect CCDirectRenderer::moveScissorToWindowSpace(const DrawingFrame& frame, Fl
oatRect scissorRect) | |
| 93 { | |
| 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 pas
s. | |
| 97 IntRect framebufferOutputRect = frame.currentRenderPass->outputRect(); | |
| 98 scissorRectInCanvasSpace.setX(scissorRectInCanvasSpace.x() - framebufferOutp
utRect.x()); | |
| 99 if (frame.flippedY && !frame.currentTexture) | |
| 100 scissorRectInCanvasSpace.setY(framebufferOutputRect.height() - (scissorR
ectInCanvasSpace.maxY() - framebufferOutputRect.y())); | |
| 101 else | |
| 102 scissorRectInCanvasSpace.setY(scissorRectInCanvasSpace.y() - framebuffer
OutputRect.y()); | |
| 103 return scissorRectInCanvasSpace; | |
| 104 } | |
| 105 | |
| 106 CCDirectRenderer::CCDirectRenderer(CCRendererClient* client, CCResourceProvider*
resourceProvider) | |
| 107 : CCRenderer(client) | |
| 108 , m_resourceProvider(resourceProvider) | |
| 109 { | |
| 110 } | |
| 111 | |
| 112 CCDirectRenderer::~CCDirectRenderer() | |
| 113 { | |
| 114 } | |
| 115 | |
| 116 void CCDirectRenderer::decideRenderPassAllocationsForFrame(const CCRenderPassLis
t& renderPassesInDrawOrder) | |
| 117 { | |
| 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 CCRenderPas
s*>(renderPassesInDrawOrder[i]->id(), renderPassesInDrawOrder[i])); | |
| 121 | |
| 122 std::vector<CCRenderPass::Id> passesToDelete; | |
| 123 ScopedPtrHashMap<CCRenderPass::Id, CachedTexture>::const_iterator passIterat
or; | |
| 124 for (passIterator = m_renderPassTextures.begin(); passIterator != m_renderPa
ssTextures.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); | |
| 128 continue; | |
| 129 } | |
| 130 | |
| 131 const CCRenderPass* renderPassInFrame = it->second; | |
| 132 const IntSize& requiredSize = renderPassTextureSize(renderPassInFrame); | |
| 133 GC3Denum requiredFormat = renderPassTextureFormat(renderPassInFrame); | |
| 134 CachedTexture* texture = passIterator->second; | |
| 135 ASSERT(texture); | |
| 136 | |
| 137 if (texture->id() && (texture->size() != requiredSize || texture->format
() != requiredFormat)) | |
| 138 texture->free(); | |
| 139 } | |
| 140 | |
| 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]); | |
| 144 | |
| 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_resourcePr
ovider); | |
| 148 m_renderPassTextures.set(renderPassesInDrawOrder[i]->id(), texture.P
ass()); | |
| 149 } | |
| 150 } | |
| 151 } | |
| 152 | |
| 153 void CCDirectRenderer::drawFrame(const CCRenderPassList& renderPassesInDrawOrder
, const CCRenderPassIdHashMap& renderPassesById) | |
| 154 { | |
| 155 const CCRenderPass* rootRenderPass = renderPassesInDrawOrder.back(); | |
| 156 ASSERT(rootRenderPass); | |
| 157 | |
| 158 DrawingFrame frame; | |
| 159 frame.renderPassesById = &renderPassesById; | |
| 160 frame.rootRenderPass = rootRenderPass; | |
| 161 frame.rootDamageRect = capabilities().usingPartialSwap ? rootRenderPass->dam
ageRect() : rootRenderPass->outputRect(); | |
| 162 frame.rootDamageRect.intersect(IntRect(IntPoint::zero(), viewportSize())); | |
| 163 | |
| 164 beginDrawingFrame(frame); | |
| 165 for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) | |
| 166 drawRenderPass(frame, renderPassesInDrawOrder[i]); | |
| 167 finishDrawingFrame(frame); | |
| 168 } | |
| 169 | |
| 170 void CCDirectRenderer::drawRenderPass(DrawingFrame& frame, const CCRenderPass* r
enderPass) | |
| 171 { | |
| 172 if (!useRenderPass(frame, renderPass)) | |
| 173 return; | |
| 174 | |
| 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::projectClippedR
ect(inverseTransformToRoot, frame.rootDamageRect)); | |
| 179 } | |
| 180 | |
| 181 enableScissorTestRect(moveScissorToWindowSpace(frame, frame.scissorRectInRen
derPassSpace)); | |
| 182 clearFramebuffer(frame); | |
| 183 | |
| 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, quadScissorRec
t)); | |
| 190 drawQuad(frame, *it); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 CachedTexture* texture = m_renderPassTextures.get(renderPass->id()); | |
| 195 if (texture) | |
| 196 texture->setIsComplete(!renderPass->hasOcclusionFromOutsideTargetSurface
()); | |
| 197 } | |
| 198 | |
| 199 bool CCDirectRenderer::useRenderPass(DrawingFrame& frame, const CCRenderPass* re
nderPass) | |
| 200 { | |
| 201 frame.currentRenderPass = renderPass; | |
| 202 frame.currentTexture = 0; | |
| 203 | |
| 204 if (renderPass == frame.rootRenderPass) { | |
| 205 bindFramebufferToOutputSurface(frame); | |
| 206 initializeMatrices(frame, renderPass->outputRect(), flippedFramebuffer()
); | |
| 207 setDrawViewportSize(renderPass->outputRect().size()); | |
| 208 return true; | |
| 209 } | |
| 210 | |
| 211 CachedTexture* texture = m_renderPassTextures.get(renderPass->id()); | |
| 212 ASSERT(texture); | |
| 213 if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, renderPassTex
tureSize(renderPass), renderPassTextureFormat(renderPass), CCResourceProvider::T
extureUsageFramebuffer)) | |
| 214 return false; | |
| 215 | |
| 216 return bindFramebufferToTexture(frame, texture, renderPass->outputRect()); | |
| 217 } | |
| 218 | |
| 219 bool CCDirectRenderer::haveCachedResourcesForRenderPassId(CCRenderPass::Id id) c
onst | |
| 220 { | |
| 221 CachedTexture* texture = m_renderPassTextures.get(id); | |
| 222 return texture && texture->id() && texture->isComplete(); | |
| 223 } | |
| 224 | |
| 225 // static | |
| 226 IntSize CCDirectRenderer::renderPassTextureSize(const CCRenderPass* pass) | |
| 227 { | |
| 228 return pass->outputRect().size(); | |
| 229 } | |
| 230 | |
| 231 // static | |
| 232 GC3Denum CCDirectRenderer::renderPassTextureFormat(const CCRenderPass*) | |
| 233 { | |
| 234 return GraphicsContext3D::RGBA; | |
| 235 } | |
| 236 | |
| 237 } | |
| OLD | NEW |