OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (C) 2012 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 | |
6 * are met: | |
7 * | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * | |
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 #include "config.h" | |
27 | |
28 #include "CCRendererSoftware.h" | |
29 | |
30 #include "CCDebugBorderDrawQuad.h" | |
31 #include "CCSolidColorDrawQuad.h" | |
32 #include "CCTextureDrawQuad.h" | |
33 #include "CCTileDrawQuad.h" | |
34 #include "SkCanvas.h" | |
35 #include "SkColor.h" | |
36 #include "SkMatrix.h" | |
37 #include "SkPixelRef.h" | |
38 #include "UnthrottledTextureUploader.h" | |
39 #include <GLES2/gl2.h> | |
40 #include <public/WebImage.h> | |
41 #include <public/WebSize.h> | |
42 #include <public/WebTransformationMatrix.h> | |
43 | |
44 using WebKit::WebCompositorSoftwareOutputDevice; | |
45 using WebKit::WebImage; | |
46 using WebKit::WebSize; | |
47 using WebKit::WebTransformationMatrix; | |
48 | |
49 namespace cc { | |
50 | |
51 namespace { | |
52 | |
53 SkRect toSkRect(const FloatRect& rect) | |
54 { | |
55 return SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); | |
56 } | |
57 | |
58 SkIRect toSkIRect(const IntRect& rect) | |
59 { | |
60 return SkIRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); | |
61 } | |
62 | |
63 void toSkMatrix(SkMatrix* flattened, const WebTransformationMatrix& m) | |
64 { | |
65 // Convert from 4x4 to 3x3 by dropping the third row and column. | |
66 flattened->set(0, m.m11()); | |
67 flattened->set(1, m.m21()); | |
68 flattened->set(2, m.m41()); | |
69 flattened->set(3, m.m12()); | |
70 flattened->set(4, m.m22()); | |
71 flattened->set(5, m.m42()); | |
72 flattened->set(6, m.m14()); | |
73 flattened->set(7, m.m24()); | |
74 flattened->set(8, m.m44()); | |
75 } | |
76 | |
77 class SoftwareTextureCopier : public TextureCopier { | |
78 WTF_MAKE_NONCOPYABLE(SoftwareTextureCopier); | |
79 public: | |
80 static PassOwnPtr<SoftwareTextureCopier> create() | |
81 { | |
82 return adoptPtr(new SoftwareTextureCopier()); | |
83 } | |
84 virtual void copyTexture(TextureCopier::Parameters) OVERRIDE { /* FIXME */ } | |
85 virtual void flush() OVERRIDE { } | |
86 | |
87 private: | |
88 SoftwareTextureCopier() { } | |
89 }; | |
90 | |
91 } // anonymous namespace | |
92 | |
93 PassOwnPtr<CCRendererSoftware> CCRendererSoftware::create(CCRendererClient* clie nt, CCResourceProvider* resourceProvider, WebCompositorSoftwareOutputDevice* out putDevice) | |
94 { | |
95 return adoptPtr(new CCRendererSoftware(client, resourceProvider, outputDevic e)); | |
96 } | |
97 | |
98 CCRendererSoftware::CCRendererSoftware(CCRendererClient* client, CCResourceProvi der* resourceProvider, WebCompositorSoftwareOutputDevice* outputDevice) | |
99 : CCDirectRenderer(client, resourceProvider) | |
100 , m_visible(true) | |
101 , m_textureCopier(SoftwareTextureCopier::create()) | |
102 , m_textureUploader(UnthrottledTextureUploader::create()) | |
103 , m_outputDevice(outputDevice) | |
104 , m_skRootCanvas(0) | |
105 , m_skCurrentCanvas(0) | |
106 { | |
107 m_resourceProvider->setDefaultResourceType(CCResourceProvider::Bitmap); | |
108 | |
109 m_capabilities.maxTextureSize = INT_MAX; | |
110 m_capabilities.bestTextureFormat = GraphicsContext3D::RGBA; | |
111 m_capabilities.contextHasCachedFrontBuffer = true; | |
112 m_capabilities.usingSetVisibility = true; | |
113 | |
114 viewportChanged(); | |
115 } | |
116 | |
117 CCRendererSoftware::~CCRendererSoftware() | |
118 { | |
119 } | |
120 | |
121 void CCRendererSoftware::viewportChanged() | |
122 { | |
123 m_outputDevice->didChangeViewportSize(WebSize(viewportSize().width(), viewpo rtSize().height())); | |
danakj
2012/09/19 18:35:14
How come the software renderer needs a call like t
aelias_OOO_until_Jul13
2012/09/19 19:58:27
For the test harness and GL adapter, they need to
danakj
2012/09/19 20:06:18
I see, thanks.
| |
124 } | |
125 | |
126 void CCRendererSoftware::beginDrawingFrame(DrawingFrame& frame) | |
127 { | |
128 m_skRootCanvas.setBitmapDevice(m_outputDevice->lock(true)->getSkBitmap()); | |
129 } | |
130 | |
131 void CCRendererSoftware::finishDrawingFrame(DrawingFrame& frame) | |
132 { | |
133 m_currentFramebufferLock.clear(); | |
134 m_skCurrentCanvas = 0; | |
135 m_skRootCanvas.setDevice(0); | |
136 m_outputDevice->unlock(); | |
137 } | |
138 | |
139 void CCRendererSoftware::finish() | |
140 { | |
141 } | |
142 | |
143 void CCRendererSoftware::bindFramebufferToOutputSurface(DrawingFrame& frame) | |
144 { | |
145 m_currentFramebufferLock.clear(); | |
146 m_skCurrentCanvas = &m_skRootCanvas; | |
147 } | |
148 | |
149 bool CCRendererSoftware::bindFramebufferToTexture(DrawingFrame& frame, const CCS copedTexture* texture, const IntRect& framebufferRect) | |
150 { | |
151 m_currentFramebufferLock = adoptPtr(new CCResourceProvider::ScopedWriteLockS oftware(m_resourceProvider, texture->id())); | |
152 m_skCurrentCanvas = m_currentFramebufferLock->skCanvas(); | |
153 initializeMatrices(frame, framebufferRect, false); | |
154 setDrawViewportSize(framebufferRect.size()); | |
155 | |
156 return true; | |
157 } | |
158 | |
159 void CCRendererSoftware::enableScissorTestRect(const IntRect& scissorRect) | |
160 { | |
161 m_skCurrentCanvas->clipRect(toSkRect(scissorRect), SkRegion::kReplace_Op); | |
162 } | |
163 | |
164 void CCRendererSoftware::disableScissorTest() | |
165 { | |
166 IntRect canvasRect(IntPoint(), viewportSize()); | |
167 m_skCurrentCanvas->clipRect(toSkRect(canvasRect), SkRegion::kReplace_Op); | |
168 } | |
169 | |
170 void CCRendererSoftware::clearFramebuffer(DrawingFrame& frame) | |
171 { | |
172 m_skCurrentCanvas->clear(SK_ColorGREEN); | |
173 } | |
174 | |
175 void CCRendererSoftware::setDrawViewportSize(const IntSize& viewportSize) | |
176 { | |
177 } | |
178 | |
179 bool CCRendererSoftware::isSoftwareResource(CCResourceProvider::ResourceId id) c onst | |
180 { | |
181 switch (m_resourceProvider->resourceType(id)) { | |
182 case CCResourceProvider::GLTexture: | |
183 return false; | |
184 case CCResourceProvider::Bitmap: | |
185 return true; | |
186 } | |
187 | |
188 CRASH(); | |
189 return false; | |
190 } | |
191 | |
192 void CCRendererSoftware::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad) | |
193 { | |
194 WebTransformationMatrix quadRectMatrix; | |
195 quadRectTransform(&quadRectMatrix, quad->quadTransform(), quad->quadRect()); | |
196 WebTransformationMatrix windowMatrix = frame.windowMatrix * frame.projection Matrix * quadRectMatrix; | |
197 SkMatrix skWindowMatrix; | |
198 toSkMatrix(&skWindowMatrix, windowMatrix); | |
199 m_skCurrentCanvas->setMatrix(skWindowMatrix); | |
200 | |
201 m_skCurrentPaint.reset(); | |
202 if (quad->needsBlending()) | |
203 m_skCurrentPaint.setAlpha(quad->opacity() * 255); | |
204 else | |
205 m_skCurrentPaint.setXfermodeMode(SkXfermode::kSrc_Mode); | |
206 | |
207 switch (quad->material()) { | |
208 case CCDrawQuad::DebugBorder: | |
209 drawDebugBorderQuad(frame, CCDebugBorderDrawQuad::materialCast(quad)); | |
210 break; | |
211 case CCDrawQuad::SolidColor: | |
212 drawSolidColorQuad(frame, CCSolidColorDrawQuad::materialCast(quad)); | |
213 break; | |
214 case CCDrawQuad::TextureContent: | |
215 drawTextureQuad(frame, CCTextureDrawQuad::materialCast(quad)); | |
216 break; | |
217 case CCDrawQuad::TiledContent: | |
218 drawTileQuad(frame, CCTileDrawQuad::materialCast(quad)); | |
219 break; | |
220 default: | |
221 drawUnsupportedQuad(frame, quad); | |
222 break; | |
223 } | |
224 | |
225 m_skCurrentCanvas->resetMatrix(); | |
226 } | |
227 | |
228 void CCRendererSoftware::drawDebugBorderQuad(const DrawingFrame& frame, const CC DebugBorderDrawQuad* quad) | |
229 { | |
230 // We need to apply the matrix manually to have pixel-sized stroke width. | |
231 SkPoint vertices[4]; | |
232 toSkRect(quadVertexRect()).toQuad(vertices); | |
233 SkPoint transformedVertices[4]; | |
234 m_skCurrentCanvas->getTotalMatrix().mapPoints(transformedVertices, vertices, 4); | |
235 m_skCurrentCanvas->resetMatrix(); | |
236 | |
237 m_skCurrentPaint.setColor(quad->color()); | |
238 m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); | |
239 m_skCurrentPaint.setStyle(SkPaint::kStroke_Style); | |
240 m_skCurrentPaint.setStrokeWidth(quad->width()); | |
241 m_skCurrentCanvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, transformedVe rtices, m_skCurrentPaint); | |
242 } | |
243 | |
244 void CCRendererSoftware::drawSolidColorQuad(const DrawingFrame& frame, const CCS olidColorDrawQuad* quad) | |
245 { | |
246 m_skCurrentPaint.setColor(quad->color()); | |
247 m_skCurrentPaint.setAlpha(quad->opacity() * SkColorGetA(quad->color())); | |
248 m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); | |
249 } | |
250 | |
251 void CCRendererSoftware::drawTextureQuad(const DrawingFrame& frame, const CCText ureDrawQuad* quad) | |
252 { | |
253 if (!isSoftwareResource(quad->resourceId())) { | |
254 drawUnsupportedQuad(frame, quad); | |
255 return; | |
256 } | |
257 | |
258 // FIXME: Add support for non-premultiplied alpha. | |
danakj
2012/09/19 18:35:14
Do you want an assert quad->premultipliedAlpha() o
| |
259 CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvid er, quad->resourceId()); | |
260 FloatRect uvRect = quad->uvRect(); | |
261 uvRect.scale(quad->quadRect().width(), quad->quadRect().height()); | |
262 SkIRect skUvRect = toSkIRect(enclosingIntRect(uvRect)); | |
263 if (quad->flipped()) | |
264 m_skCurrentCanvas->scale(1, -1); | |
265 m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &skUvRect, t oSkRect(quadVertexRect()), &m_skCurrentPaint); | |
266 } | |
267 | |
268 void CCRendererSoftware::drawTileQuad(const DrawingFrame& frame, const CCTileDra wQuad* quad) | |
269 { | |
270 ASSERT(isSoftwareResource(quad->resourceId())); | |
271 CCResourceProvider::ScopedReadLockSoftware quadResourceLock(m_resourceProvid er, quad->resourceId()); | |
272 | |
273 SkIRect uvRect = toSkIRect(IntRect(quad->textureOffset(), quad->quadRect().s ize())); | |
274 m_skCurrentCanvas->drawBitmapRect(*quadResourceLock.skBitmap(), &uvRect, toS kRect(quadVertexRect()), &m_skCurrentPaint); | |
275 } | |
276 | |
277 void CCRendererSoftware::drawUnsupportedQuad(const DrawingFrame& frame, const CC DrawQuad* quad) | |
278 { | |
279 m_skCurrentPaint.setColor(SK_ColorMAGENTA); | |
280 m_skCurrentPaint.setAlpha(quad->opacity() * 255); | |
281 m_skCurrentCanvas->drawRect(toSkRect(quadVertexRect()), m_skCurrentPaint); | |
282 } | |
283 | |
284 bool CCRendererSoftware::swapBuffers() | |
285 { | |
286 if (CCProxy::hasImplThread()) | |
287 m_client->onSwapBuffersComplete(); | |
288 return true; | |
289 } | |
290 | |
291 void CCRendererSoftware::getFramebufferPixels(void *pixels, const IntRect& rect) | |
292 { | |
293 SkBitmap fullBitmap = m_outputDevice->lock(false)->getSkBitmap(); | |
294 SkBitmap subsetBitmap; | |
295 SkIRect invertRect = SkIRect::MakeXYWH(rect.x(), viewportSize().height() - r ect.maxY(), rect.width(), rect.height()); | |
296 fullBitmap.extractSubset(&subsetBitmap, invertRect); | |
297 subsetBitmap.copyPixelsTo(pixels, rect.width() * rect.height() * 4, rect.wid th() * 4); | |
298 m_outputDevice->unlock(); | |
299 } | |
300 | |
301 void CCRendererSoftware::setVisible(bool visible) | |
302 { | |
303 if (m_visible == visible) | |
304 return; | |
305 m_visible = visible; | |
306 } | |
307 | |
308 } | |
OLD | NEW |