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 #include "config.h"
32 
33 #if ENABLE(ACCELERATED_2D_CANVAS)
34 #include "SharedGraphicsContext3D.h"
35 
36 #include "AffineTransform.h"
37 #include "BicubicShader.h"
38 #include "Color.h"
39 #include "ConvolutionShader.h"
40 #include "DrawingBuffer.h"
41 #include "Extensions3D.h"
42 #include "FloatRect.h"
43 #include "IntSize.h"
44 #include "LoopBlinnSolidFillShader.h"
45 #include "SolidFillShader.h"
46 #include "TexShader.h"
47 
48 #if USE(SKIA)
49 #include "GrContext.h"
50 #endif
51 
52 // Limit the number of textures we hold in the bitmap->texture cache.
53 static const int maxTextureCacheCount = 512;
54 // Limit the bytes allocated toward textures in the bitmap->texture cache.
55 static const size_t maxTextureCacheBytes = 50 * 1024 * 1024;
56 
57 #include <wtf/OwnArrayPtr.h>
58 #include <wtf/text/CString.h>
59 #include <wtf/text/WTFString.h>
60 
61 namespace WebCore {
62 
63 // static
create(HostWindow * hostWindow,CreationFlags flags)64 PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(HostWindow* hostWindow, CreationFlags flags)
65 {
66     GraphicsContext3D::Attributes attr;
67     attr.depth = false;
68     attr.stencil = true;
69     attr.antialias = useLoopBlinnForPathRendering();
70     attr.canRecoverFromContextLoss = false; // Canvas contexts can not handle lost contexts.
71     RefPtr<GraphicsContext3D> context = GraphicsContext3D::create(attr, hostWindow);
72     if (!context)
73         return 0;
74     OwnPtr<SolidFillShader> solidFillShader = SolidFillShader::create(context.get());
75     if (!solidFillShader)
76         return 0;
77     OwnPtr<TexShader> texShader = TexShader::create(context.get());
78     if (!texShader)
79         return 0;
80     OwnPtr<BicubicShader> bicubicShader = BicubicShader::create(context.get());
81     if (!bicubicShader)
82         return 0;
83     OwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders = adoptArrayPtr(new OwnPtr<ConvolutionShader>[cMaxKernelWidth]);
84     for (int i = 0; i < cMaxKernelWidth; ++i) {
85         convolutionShaders[i] = ConvolutionShader::create(context.get(), i + 1);
86         if (!convolutionShaders[i])
87             return 0;
88     }
89     return adoptRef(new SharedGraphicsContext3D(context.release(), solidFillShader.release(), texShader.release(), bicubicShader.release(), convolutionShaders.release(), flags));
90 }
91 
92 
SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context,PassOwnPtr<SolidFillShader> solidFillShader,PassOwnPtr<TexShader> texShader,PassOwnPtr<BicubicShader> bicubicShader,PassOwnArrayPtr<OwnPtr<ConvolutionShader>> convolutionShaders,CreationFlags flags)93 SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader, PassOwnPtr<BicubicShader> bicubicShader, PassOwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders, CreationFlags flags)
94     : m_context(context)
95     , m_bgraSupported(false)
96     , m_quadVertices(0)
97     , m_solidFillShader(solidFillShader)
98     , m_texShader(texShader)
99     , m_bicubicShader(bicubicShader)
100     , m_convolutionShaders(convolutionShaders)
101     , m_oesStandardDerivativesSupported(false)
102     , m_flags(flags)
103 #if USE(SKIA)
104     , m_grContext(0)
105 #endif
106 {
107     allContexts()->add(this);
108     Extensions3D* extensions = m_context->getExtensions();
109     m_bgraSupported = extensions->supports("GL_EXT_texture_format_BGRA8888") && extensions->supports("GL_EXT_read_format_bgra");
110     if (m_bgraSupported) {
111         extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888");
112         extensions->ensureEnabled("GL_EXT_read_format_bgra");
113     }
114     m_oesStandardDerivativesSupported = extensions->supports("GL_OES_standard_derivatives");
115     if (m_oesStandardDerivativesSupported)
116         extensions->ensureEnabled("GL_OES_standard_derivatives");
117 }
118 
~SharedGraphicsContext3D()119 SharedGraphicsContext3D::~SharedGraphicsContext3D()
120 {
121     m_context->deleteBuffer(m_quadVertices);
122     allContexts()->remove(this);
123 #if USE(SKIA)
124     GrSafeUnref(m_grContext);
125 #endif
126 }
127 
makeContextCurrent()128 void SharedGraphicsContext3D::makeContextCurrent()
129 {
130     m_context->makeContextCurrent();
131 }
132 
scissor(GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height)133 void SharedGraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
134 {
135     m_context->scissor(x, y, width, height);
136 }
137 
enable(GC3Denum capacity)138 void SharedGraphicsContext3D::enable(GC3Denum capacity)
139 {
140     m_context->enable(capacity);
141 }
142 
disable(GC3Denum capacity)143 void SharedGraphicsContext3D::disable(GC3Denum capacity)
144 {
145     m_context->disable(capacity);
146 }
147 
clearColor(const Color & color)148 void SharedGraphicsContext3D::clearColor(const Color& color)
149 {
150     float rgba[4];
151     color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
152     m_context->clearColor(rgba[0], rgba[1], rgba[2], rgba[3]);
153 }
154 
clear(GC3Dbitfield mask)155 void SharedGraphicsContext3D::clear(GC3Dbitfield mask)
156 {
157     m_context->clear(mask);
158 }
159 
drawArrays(GC3Denum mode,GC3Dint first,GC3Dsizei count)160 void SharedGraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
161 {
162     m_context->drawArrays(mode, first, count);
163 }
164 
getError()165 GC3Denum SharedGraphicsContext3D::getError()
166 {
167     return m_context->getError();
168 }
169 
getIntegerv(GC3Denum pname,GC3Dint * value)170 void SharedGraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
171 {
172     m_context->getIntegerv(pname, value);
173 }
174 
flush()175 void SharedGraphicsContext3D::flush()
176 {
177     m_context->flush();
178 }
179 
createBuffer()180 Platform3DObject SharedGraphicsContext3D::createBuffer()
181 {
182     return m_context->createBuffer();
183 }
184 
createFramebuffer()185 Platform3DObject SharedGraphicsContext3D::createFramebuffer()
186 {
187     return m_context->createFramebuffer();
188 }
189 
createTexture()190 Platform3DObject SharedGraphicsContext3D::createTexture()
191 {
192     return m_context->createTexture();
193 }
194 
deleteFramebuffer(Platform3DObject framebuffer)195 void SharedGraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer)
196 {
197     m_context->deleteFramebuffer(framebuffer);
198 }
199 
deleteTexture(Platform3DObject texture)200 void SharedGraphicsContext3D::deleteTexture(Platform3DObject texture)
201 {
202     m_context->deleteTexture(texture);
203 }
204 
framebufferTexture2D(GC3Denum target,GC3Denum attachment,GC3Denum textarget,Platform3DObject texture,GC3Dint level)205 void SharedGraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
206 {
207     m_context->framebufferTexture2D(target, attachment, textarget, texture, level);
208 }
209 
texParameteri(GC3Denum target,GC3Denum pname,GC3Dint param)210 void SharedGraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
211 {
212     m_context->texParameteri(target, pname, param);
213 }
214 
texImage2D(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Dsizei width,GC3Dsizei height,GC3Dint border,GC3Denum format,GC3Denum type,const void * pixels)215 bool SharedGraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
216 {
217     if (!pixels)
218         return m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border, format, type);
219     return m_context->texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
220 }
221 
texSubImage2D(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Dsizei width,GC3Dsizei height,GC3Denum format,GC3Denum type,const void * pixels)222 void SharedGraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels)
223 {
224     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
225 }
226 
readPixels(GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height,GC3Denum format,GC3Denum type,void * data)227 void SharedGraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data)
228 {
229     m_context->readPixels(x, y, width, height, format, type, data);
230 }
231 
supportsBGRA()232 bool SharedGraphicsContext3D::supportsBGRA()
233 {
234     return m_bgraSupported;
235 }
236 
supportsCompositeOp(CompositeOperator op) const237 bool SharedGraphicsContext3D::supportsCompositeOp(CompositeOperator op) const
238 {
239 #if USE(SKIA)
240     return m_flags & UseSkiaGPU || op == CompositeSourceOver;
241 #else
242     return op == CompositeSourceOver;
243 #endif
244 }
245 
createTexture(NativeImagePtr ptr,Texture::Format format,int width,int height)246 Texture* SharedGraphicsContext3D::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height)
247 {
248     RefPtr<Texture> texture = m_textures.get(ptr);
249     if (texture)
250         return texture.get();
251 
252     texture = Texture::create(m_context.get(), format, width, height);
253     Texture* t = texture.get();
254     m_textures.set(ptr, texture);
255     return t;
256 }
257 
getTexture(NativeImagePtr ptr)258 Texture* SharedGraphicsContext3D::getTexture(NativeImagePtr ptr)
259 {
260     RefPtr<Texture> texture = m_textures.get(ptr);
261     return texture ? texture.get() : 0;
262 }
263 
removeTextureFor(NativeImagePtr ptr)264 void SharedGraphicsContext3D::removeTextureFor(NativeImagePtr ptr)
265 {
266     TextureHashMap::iterator it = m_textures.find(ptr);
267     if (it != m_textures.end())
268         m_textures.remove(it);
269 }
270 
271 // static
removeTexturesFor(NativeImagePtr ptr)272 void SharedGraphicsContext3D::removeTexturesFor(NativeImagePtr ptr)
273 {
274     for (HashSet<SharedGraphicsContext3D*>::iterator it = allContexts()->begin(); it != allContexts()->end(); ++it)
275         (*it)->removeTextureFor(ptr);
276 }
277 
278 // static
allContexts()279 HashSet<SharedGraphicsContext3D*>* SharedGraphicsContext3D::allContexts()
280 {
281     DEFINE_STATIC_LOCAL(HashSet<SharedGraphicsContext3D*>, allContextsSet, ());
282     return &allContextsSet;
283 }
284 
285 
createTexture(Texture::Format format,int width,int height)286 PassRefPtr<Texture> SharedGraphicsContext3D::createTexture(Texture::Format format, int width, int height)
287 {
288     return Texture::create(m_context.get(), format, width, height);
289 }
290 
applyCompositeOperator(CompositeOperator op)291 void SharedGraphicsContext3D::applyCompositeOperator(CompositeOperator op)
292 {
293     switch (op) {
294     case CompositeClear:
295         m_context->enable(GraphicsContext3D::BLEND);
296         m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::ZERO);
297         break;
298     case CompositeCopy:
299         m_context->disable(GraphicsContext3D::BLEND);
300         break;
301     case CompositeSourceOver:
302         m_context->enable(GraphicsContext3D::BLEND);
303         m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
304         break;
305     case CompositeSourceIn:
306         m_context->enable(GraphicsContext3D::BLEND);
307         m_context->blendFunc(GraphicsContext3D::DST_ALPHA, GraphicsContext3D::ZERO);
308         break;
309     case CompositeSourceOut:
310         m_context->enable(GraphicsContext3D::BLEND);
311         m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ZERO);
312         break;
313     case CompositeSourceAtop:
314         m_context->enable(GraphicsContext3D::BLEND);
315         m_context->blendFunc(GraphicsContext3D::DST_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
316         break;
317     case CompositeDestinationOver:
318         m_context->enable(GraphicsContext3D::BLEND);
319         m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ONE);
320         break;
321     case CompositeDestinationIn:
322         m_context->enable(GraphicsContext3D::BLEND);
323         m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::SRC_ALPHA);
324         break;
325     case CompositeDestinationOut:
326         m_context->enable(GraphicsContext3D::BLEND);
327         m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
328         break;
329     case CompositeDestinationAtop:
330         m_context->enable(GraphicsContext3D::BLEND);
331         m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::SRC_ALPHA);
332         break;
333     case CompositeXOR:
334         m_context->enable(GraphicsContext3D::BLEND);
335         m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
336         break;
337     case CompositePlusDarker:
338     case CompositeHighlight:
339         // unsupported
340         m_context->disable(GraphicsContext3D::BLEND);
341         break;
342     case CompositePlusLighter:
343         m_context->enable(GraphicsContext3D::BLEND);
344         m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE);
345         break;
346     }
347 }
348 
enableStencil(bool enable)349 void SharedGraphicsContext3D::enableStencil(bool enable)
350 {
351     if (enable)
352         m_context->enable(GraphicsContext3D::STENCIL_TEST);
353     else
354         m_context->disable(GraphicsContext3D::STENCIL_TEST);
355 }
356 
useQuadVertices()357 void SharedGraphicsContext3D::useQuadVertices()
358 {
359     if (!m_quadVertices) {
360         float vertices[] = { 0.0f, 0.0f,
361                              1.0f, 0.0f,
362                              0.0f, 1.0f,
363                              1.0f, 1.0f };
364         m_quadVertices = m_context->createBuffer();
365         m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVertices);
366         m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW);
367     } else {
368         m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVertices);
369     }
370 }
371 
setActiveTexture(GC3Denum textureUnit)372 void SharedGraphicsContext3D::setActiveTexture(GC3Denum textureUnit)
373 {
374     m_context->activeTexture(textureUnit);
375 }
376 
bindBuffer(GC3Denum target,Platform3DObject buffer)377 void SharedGraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
378 {
379     m_context->bindBuffer(target, buffer);
380 }
381 
bindTexture(GC3Denum target,Platform3DObject texture)382 void SharedGraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture)
383 {
384     m_context->bindTexture(target, texture);
385 }
386 
bufferData(GC3Denum target,GC3Dsizeiptr size,GC3Denum usage)387 void SharedGraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
388 {
389     m_context->bufferData(target, size, usage);
390 }
391 
bufferData(GC3Denum target,GC3Dsizeiptr size,const void * data,GC3Denum usage)392 void SharedGraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
393 {
394     m_context->bufferData(target, size, data, usage);
395 }
396 
bufferSubData(GC3Denum target,GC3Dintptr offset,GC3Dsizeiptr size,const void * data)397 void SharedGraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data)
398 {
399     m_context->bufferSubData(target, offset, size, data);
400 }
401 
useFillSolidProgram(const AffineTransform & transform,const Color & color)402 void SharedGraphicsContext3D::useFillSolidProgram(const AffineTransform& transform, const Color& color)
403 {
404     m_solidFillShader->use(transform, color);
405 }
406 
useTextureProgram(const AffineTransform & transform,const AffineTransform & texTransform,float alpha)407 void SharedGraphicsContext3D::useTextureProgram(const AffineTransform& transform, const AffineTransform& texTransform, float alpha)
408 {
409     m_texShader->use(transform, texTransform, 0, alpha);
410 }
411 
useBicubicProgram(const AffineTransform & transform,const AffineTransform & texTransform,const float coefficients[16],const float imageIncrement[2],float alpha)412 void SharedGraphicsContext3D::useBicubicProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha)
413 {
414     m_bicubicShader->use(transform, texTransform, coefficients, imageIncrement, alpha);
415 }
416 
useConvolutionProgram(const AffineTransform & transform,const AffineTransform & texTransform,const float * kernel,int kernelWidth,float imageIncrement[2])417 void SharedGraphicsContext3D::useConvolutionProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2])
418 {
419     ASSERT(kernelWidth >= 1 && kernelWidth <= cMaxKernelWidth);
420     m_convolutionShaders[kernelWidth - 1]->use(transform, texTransform, kernel, kernelWidth, imageIncrement);
421 }
422 
bindFramebuffer(Platform3DObject framebuffer)423 void SharedGraphicsContext3D::bindFramebuffer(Platform3DObject framebuffer)
424 {
425     m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
426 }
427 
setViewport(const IntSize & size)428 void SharedGraphicsContext3D::setViewport(const IntSize& size)
429 {
430     m_context->viewport(0, 0, size.width(), size.height());
431 }
432 
paintsIntoCanvasBuffer() const433 bool SharedGraphicsContext3D::paintsIntoCanvasBuffer() const
434 {
435     return m_context->paintsIntoCanvasBuffer();
436 }
437 
useLoopBlinnForPathRendering()438 bool SharedGraphicsContext3D::useLoopBlinnForPathRendering()
439 {
440     return false;
441 }
442 
useLoopBlinnInteriorProgram(unsigned vertexOffset,const AffineTransform & transform,const Color & color)443 void SharedGraphicsContext3D::useLoopBlinnInteriorProgram(unsigned vertexOffset, const AffineTransform& transform, const Color& color)
444 {
445     if (!m_loopBlinnInteriorShader) {
446         m_loopBlinnInteriorShader = LoopBlinnSolidFillShader::create(m_context.get(),
447                                                                      LoopBlinnShader::Interior,
448                                                                      Shader::NotAntialiased);
449     }
450     ASSERT(m_loopBlinnInteriorShader);
451     m_loopBlinnInteriorShader->use(vertexOffset, 0, transform, color);
452 }
453 
useLoopBlinnExteriorProgram(unsigned vertexOffset,unsigned klmOffset,const AffineTransform & transform,const Color & color)454 void SharedGraphicsContext3D::useLoopBlinnExteriorProgram(unsigned vertexOffset, unsigned klmOffset, const AffineTransform& transform, const Color& color)
455 {
456     if (!m_loopBlinnExteriorShader) {
457         m_loopBlinnExteriorShader = LoopBlinnSolidFillShader::create(m_context.get(),
458                                                                      LoopBlinnShader::Exterior,
459                                                                      m_oesStandardDerivativesSupported ? Shader::Antialiased : Shader::NotAntialiased);
460     }
461     ASSERT(m_loopBlinnExteriorShader);
462     m_loopBlinnExteriorShader->use(vertexOffset, klmOffset, transform, color);
463 }
464 
getOffscreenBuffer(unsigned index,const IntSize & size)465 DrawingBuffer* SharedGraphicsContext3D::getOffscreenBuffer(unsigned index, const IntSize& size)
466 {
467     if (index >= m_offscreenBuffers.size())
468         m_offscreenBuffers.resize(index + 1);
469 
470     if (!m_offscreenBuffers[index])
471         m_offscreenBuffers[index] = m_context->createDrawingBuffer(size);
472 
473     if (size.width() != m_offscreenBuffers[index]->size().width()
474         || size.height() != m_offscreenBuffers[index]->size().height())
475         m_offscreenBuffers[index]->reset(size);
476     return m_offscreenBuffers[index].get();
477 }
478 
479 #if USE(SKIA)
grContext()480 GrContext* SharedGraphicsContext3D::grContext()
481 {
482     if (!(m_flags & UseSkiaGPU))
483         return 0;
484     if (!m_grContext) {
485         m_grContext = GrContext::CreateGLShaderContext();
486         m_grContext->setTextureCacheLimits(maxTextureCacheCount, maxTextureCacheBytes);
487     }
488     return m_grContext;
489 }
490 #endif
491 
492 } // namespace WebCore
493 
494 #endif
495