Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include "ogl_spritedevicehelper.hxx"
11 : #include "ogl_spritecanvas.hxx"
12 : #include "ogl_canvasbitmap.hxx"
13 : #include "ogl_canvastools.hxx"
14 : #include "ogl_canvascustomsprite.hxx"
15 : #include "ogl_texturecache.hxx"
16 :
17 : #include <canvas/verbosetrace.hxx>
18 : #include <basegfx/tools/canvastools.hxx>
19 : #include <basegfx/tools/unopolypolygon.hxx>
20 :
21 : #include <osl/mutex.hxx>
22 : #include <rtl/instance.hxx>
23 : #include <com/sun/star/uno/Reference.hxx>
24 : #include <com/sun/star/lang/NoSupportException.hpp>
25 : #include <com/sun/star/rendering/XColorSpace.hpp>
26 : #include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
27 :
28 : #include <vcl/sysdata.hxx>
29 : #include <vcl/syschild.hxx>
30 : #include <vcl/canvastools.hxx>
31 : #include <toolkit/helper/vclunohelper.hxx>
32 :
33 : #include <vcl/opengl/OpenGLHelper.hxx>
34 :
35 : using namespace ::com::sun::star;
36 :
37 0 : static void initContext()
38 : {
39 : // need the backside for mirror effects
40 0 : glDisable(GL_CULL_FACE);
41 :
42 : // no perspective, we're 2D
43 0 : glMatrixMode(GL_PROJECTION);
44 0 : glLoadIdentity();
45 :
46 : // misc preferences
47 0 : glEnable(GL_POINT_SMOOTH);
48 0 : glEnable(GL_LINE_SMOOTH);
49 0 : glEnable(GL_POLYGON_SMOOTH);
50 0 : glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
51 0 : glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
52 0 : glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
53 0 : glShadeModel(GL_FLAT);
54 0 : }
55 :
56 0 : static void initTransformation(const ::Size& rSize, bool bMirror=false)
57 : {
58 : // use whole window
59 : glViewport( 0,0,
60 0 : (GLsizei)rSize.Width(),
61 0 : (GLsizei)rSize.Height() );
62 :
63 : // model coordinate system is already in device pixel
64 0 : glMatrixMode(GL_MODELVIEW);
65 0 : glLoadIdentity();
66 0 : glTranslated(-1.0, (bMirror ? -1.0 : 1.0), 0.0);
67 0 : glScaled( 2.0 / rSize.Width(),
68 0 : (bMirror ? 2.0 : -2.0) / rSize.Height(),
69 0 : 1.0 );
70 :
71 : // clear to black
72 0 : glClearColor(0,0,0,0);
73 0 : glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
74 0 : }
75 :
76 : namespace oglcanvas
77 : {
78 :
79 0 : SpriteDeviceHelper::SpriteDeviceHelper() :
80 : mpDevice(NULL),
81 : mpSpriteCanvas(NULL),
82 : maActiveSprites(),
83 : maLastUpdate(),
84 0 : mpTextureCache(new TextureCache()),
85 : mnLinearTwoColorGradientProgram(0),
86 : mnLinearMultiColorGradientProgram(0),
87 : mnRadialTwoColorGradientProgram(0),
88 : mnRadialMultiColorGradientProgram(0),
89 : mnRectangularTwoColorGradientProgram(0),
90 0 : mnRectangularMultiColorGradientProgram(0)
91 0 : {}
92 :
93 0 : SpriteDeviceHelper::~SpriteDeviceHelper()
94 0 : {}
95 :
96 0 : void SpriteDeviceHelper::init( vcl::Window& rWindow,
97 : SpriteCanvas& rSpriteCanvas,
98 : const awt::Rectangle& rViewArea )
99 : {
100 0 : mpSpriteCanvas = &rSpriteCanvas;
101 :
102 : rSpriteCanvas.setWindow(
103 : uno::Reference<awt::XWindow2>(
104 : VCLUnoHelper::GetInterface(&rWindow),
105 0 : uno::UNO_QUERY_THROW) );
106 :
107 0 : maContext.requestLegacyContext();
108 0 : maContext.init(&rWindow);
109 : // init window context
110 0 : initContext();
111 :
112 : mnLinearMultiColorGradientProgram =
113 0 : OpenGLHelper::LoadShaders("dummyVertexShader", "linearMultiColorGradientFragmentShader");
114 :
115 : mnLinearTwoColorGradientProgram =
116 0 : OpenGLHelper::LoadShaders("dummyVertexShader", "linearTwoColorGradientFragmentShader");
117 :
118 : mnRadialMultiColorGradientProgram =
119 0 : OpenGLHelper::LoadShaders("dummyVertexShader", "radialMultiColorGradientFragmentShader");
120 :
121 : mnRadialTwoColorGradientProgram =
122 0 : OpenGLHelper::LoadShaders("dummyVertexShader", "radialTwoColorGradientFragmentShader");
123 :
124 : mnRectangularMultiColorGradientProgram =
125 0 : OpenGLHelper::LoadShaders("dummyVertexShader", "rectangularMultiColorGradientFragmentShader");
126 :
127 : mnRectangularTwoColorGradientProgram =
128 0 : OpenGLHelper::LoadShaders("dummyVertexShader", "rectangularTwoColorGradientFragmentShader");
129 :
130 0 : maContext.makeCurrent();
131 :
132 0 : notifySizeUpdate(rViewArea);
133 : // TODO(E3): check for GL_ARB_imaging extension
134 0 : }
135 :
136 0 : void SpriteDeviceHelper::disposing()
137 : {
138 : // release all references
139 0 : mpSpriteCanvas = NULL;
140 0 : mpDevice = NULL;
141 0 : mpTextureCache.reset();
142 :
143 0 : if( maContext.isInitialized() )
144 : {
145 0 : glDeleteProgram( mnRectangularTwoColorGradientProgram );
146 0 : glDeleteProgram( mnRectangularMultiColorGradientProgram );
147 0 : glDeleteProgram( mnRadialTwoColorGradientProgram );
148 0 : glDeleteProgram( mnRadialMultiColorGradientProgram );
149 0 : glDeleteProgram( mnLinearTwoColorGradientProgram );
150 0 : glDeleteProgram( mnLinearMultiColorGradientProgram );
151 : }
152 0 : }
153 :
154 0 : geometry::RealSize2D SpriteDeviceHelper::getPhysicalResolution()
155 : {
156 0 : if( !maContext.isInitialized() )
157 0 : return ::canvas::tools::createInfiniteSize2D(); // we're disposed
158 :
159 : // Map a one-by-one millimeter box to pixel
160 0 : SystemChildWindow* pChildWindow = maContext.getChildWindow();
161 0 : const MapMode aOldMapMode( pChildWindow->GetMapMode() );
162 0 : pChildWindow->SetMapMode( MapMode(MAP_MM) );
163 0 : const Size aPixelSize( pChildWindow->LogicToPixel(Size(1,1)) );
164 0 : pChildWindow->SetMapMode( aOldMapMode );
165 :
166 0 : return vcl::unotools::size2DFromSize( aPixelSize );
167 : }
168 :
169 0 : geometry::RealSize2D SpriteDeviceHelper::getPhysicalSize()
170 : {
171 0 : if( !maContext.isInitialized() )
172 0 : return ::canvas::tools::createInfiniteSize2D(); // we're disposed
173 :
174 : // Map the pixel dimensions of the output window to millimeter
175 0 : SystemChildWindow* pChildWindow = maContext.getChildWindow();
176 0 : const MapMode aOldMapMode( pChildWindow->GetMapMode() );
177 0 : pChildWindow->SetMapMode( MapMode(MAP_MM) );
178 0 : const Size aLogSize( pChildWindow->PixelToLogic(pChildWindow->GetOutputSizePixel()) );
179 0 : pChildWindow->SetMapMode( aOldMapMode );
180 :
181 0 : return vcl::unotools::size2DFromSize( aLogSize );
182 : }
183 :
184 0 : uno::Reference< rendering::XLinePolyPolygon2D > SpriteDeviceHelper::createCompatibleLinePolyPolygon(
185 : const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
186 : const uno::Sequence< uno::Sequence< geometry::RealPoint2D > >& points )
187 : {
188 : // disposed?
189 0 : if( !mpSpriteCanvas )
190 0 : return uno::Reference< rendering::XLinePolyPolygon2D >(); // we're disposed
191 :
192 : return uno::Reference< rendering::XLinePolyPolygon2D >(
193 : new ::basegfx::unotools::UnoPolyPolygon(
194 0 : ::basegfx::unotools::polyPolygonFromPoint2DSequenceSequence( points )));
195 : }
196 :
197 0 : uno::Reference< rendering::XBezierPolyPolygon2D > SpriteDeviceHelper::createCompatibleBezierPolyPolygon(
198 : const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
199 : const uno::Sequence< uno::Sequence< geometry::RealBezierSegment2D > >& points )
200 : {
201 : // disposed?
202 0 : if( !mpSpriteCanvas )
203 0 : return uno::Reference< rendering::XBezierPolyPolygon2D >(); // we're disposed
204 :
205 : return uno::Reference< rendering::XBezierPolyPolygon2D >(
206 : new ::basegfx::unotools::UnoPolyPolygon(
207 0 : ::basegfx::unotools::polyPolygonFromBezier2DSequenceSequence( points ) ) );
208 : }
209 :
210 0 : uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleBitmap(
211 : const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
212 : const geometry::IntegerSize2D& size )
213 : {
214 : // disposed?
215 0 : if( !mpSpriteCanvas )
216 0 : return uno::Reference< rendering::XBitmap >(); // we're disposed
217 :
218 : return uno::Reference< rendering::XBitmap >(
219 : new CanvasBitmap( size,
220 : mpSpriteCanvas,
221 : *this,
222 0 : false ) );
223 : }
224 :
225 0 : uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileBitmap(
226 : const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
227 : const geometry::IntegerSize2D& /*size*/ )
228 : {
229 0 : return uno::Reference< rendering::XVolatileBitmap >();
230 : }
231 :
232 0 : uno::Reference< rendering::XBitmap > SpriteDeviceHelper::createCompatibleAlphaBitmap(
233 : const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
234 : const geometry::IntegerSize2D& size )
235 : {
236 : // disposed?
237 0 : if( !mpSpriteCanvas )
238 0 : return uno::Reference< rendering::XBitmap >(); // we're disposed
239 :
240 : return uno::Reference< rendering::XBitmap >(
241 : new CanvasBitmap( size,
242 : mpSpriteCanvas,
243 : *this,
244 0 : true ) );
245 : }
246 :
247 0 : uno::Reference< rendering::XVolatileBitmap > SpriteDeviceHelper::createVolatileAlphaBitmap(
248 : const uno::Reference< rendering::XGraphicDevice >& /*rDevice*/,
249 : const geometry::IntegerSize2D& /*size*/ )
250 : {
251 0 : return uno::Reference< rendering::XVolatileBitmap >();
252 : }
253 :
254 : namespace
255 : {
256 : /** Functor providing a StrictWeakOrdering for XSprites (over
257 : priority)
258 : */
259 : struct SpriteComparator
260 : {
261 0 : bool operator()( const ::rtl::Reference<CanvasCustomSprite>& rLHS,
262 : const ::rtl::Reference<CanvasCustomSprite>& rRHS ) const
263 : {
264 0 : const double nPrioL( rLHS->getPriority() );
265 0 : const double nPrioR( rRHS->getPriority() );
266 :
267 : // if prios are equal, tie-break on ptr value
268 0 : return nPrioL == nPrioR ? rLHS.get() < rRHS.get() : nPrioL < nPrioR;
269 : }
270 : };
271 : }
272 :
273 0 : bool SpriteDeviceHelper::showBuffer( bool bIsVisible, bool /*bUpdateAll*/ )
274 : {
275 : // hidden or disposed?
276 0 : if( !bIsVisible || !maContext.isInitialized() || !mpSpriteCanvas )
277 0 : return false;
278 :
279 0 : if( !activateWindowContext() )
280 0 : return false;
281 :
282 0 : SystemChildWindow* pChildWindow = maContext.getChildWindow();
283 0 : const ::Size& rOutputSize = pChildWindow->GetSizePixel();
284 0 : initTransformation(rOutputSize);
285 :
286 : // render the actual spritecanvas content
287 0 : mpSpriteCanvas->renderRecordedActions();
288 :
289 : // render all sprites (in order of priority) on top of that
290 0 : std::vector< ::rtl::Reference<CanvasCustomSprite> > aSprites;
291 : std::copy(maActiveSprites.begin(),
292 : maActiveSprites.end(),
293 : std::back_insert_iterator<
294 0 : std::vector< ::rtl::Reference< CanvasCustomSprite > > >(aSprites));
295 : std::sort(aSprites.begin(),
296 : aSprites.end(),
297 0 : SpriteComparator());
298 : std::for_each(aSprites.begin(),
299 : aSprites.end(),
300 0 : boost::mem_fn(&CanvasCustomSprite::renderSprite));
301 :
302 :
303 : // frame counter, other info
304 0 : glMatrixMode(GL_MODELVIEW);
305 0 : glLoadIdentity();
306 0 : glTranslated(-1.0, 1.0, 0.0);
307 0 : glScaled( 2.0 / rOutputSize.Width(),
308 0 : -2.0 / rOutputSize.Height(),
309 0 : 1.0 );
310 :
311 0 : const double denominator( maLastUpdate.getElapsedTime() );
312 0 : maLastUpdate.reset();
313 :
314 0 : const double fps(denominator == 0.0 ? 100.0 : 1.0/denominator);
315 0 : std::vector<double> aVec; aVec.push_back(fps);
316 0 : aVec.push_back(maActiveSprites.size());
317 0 : aVec.push_back(mpTextureCache->getCacheSize());
318 0 : aVec.push_back(mpTextureCache->getCacheMissCount());
319 0 : aVec.push_back(mpTextureCache->getCacheHitCount());
320 0 : renderOSD( aVec, 20 );
321 :
322 : /*
323 : * TODO: moggi: fix it!
324 : // switch buffer, sync etc.
325 : const unx::Window aXWindow=pChildWindow->GetSystemData()->aWindow;
326 : unx::glXSwapBuffers(reinterpret_cast<unx::Display*>(mpDisplay),
327 : aXWindow);
328 : pChildWindow->Show();
329 : unx::glXWaitGL();
330 : XSync( reinterpret_cast<unx::Display*>(mpDisplay), false );
331 : */
332 0 : maContext.swapBuffers();
333 :
334 : // flush texture cache, such that it does not build up
335 : // indefinitely.
336 : // TODO: have max cache size/LRU time in config, prune only on
337 : // demand
338 0 : mpTextureCache->prune();
339 :
340 0 : return true;
341 : }
342 :
343 0 : bool SpriteDeviceHelper::switchBuffer( bool bIsVisible, bool bUpdateAll )
344 : {
345 : // no difference for VCL canvas
346 0 : return showBuffer( bIsVisible, bUpdateAll );
347 : }
348 :
349 0 : uno::Any SpriteDeviceHelper::isAccelerated() const
350 : {
351 0 : return ::com::sun::star::uno::makeAny(false);
352 : }
353 :
354 0 : uno::Any SpriteDeviceHelper::getDeviceHandle() const
355 : {
356 0 : const SystemChildWindow* pChildWindow = maContext.getChildWindow();
357 0 : return uno::makeAny( reinterpret_cast< sal_Int64 >(pChildWindow) );
358 : }
359 :
360 0 : uno::Any SpriteDeviceHelper::getSurfaceHandle() const
361 : {
362 0 : return uno::Any();
363 : }
364 :
365 0 : uno::Reference<rendering::XColorSpace> SpriteDeviceHelper::getColorSpace() const
366 : {
367 : // always the same
368 : return uno::Reference<rendering::XColorSpace>(
369 : ::canvas::tools::getStdColorSpace(),
370 0 : uno::UNO_QUERY);
371 : }
372 :
373 0 : void SpriteDeviceHelper::notifySizeUpdate( const awt::Rectangle& rBounds )
374 : {
375 0 : if( maContext.isInitialized() )
376 : {
377 0 : SystemChildWindow* pChildWindow = maContext.getChildWindow();
378 : pChildWindow->setPosSizePixel(
379 0 : 0,0,rBounds.Width,rBounds.Height);
380 : }
381 0 : }
382 :
383 0 : void SpriteDeviceHelper::dumpScreenContent() const
384 : {
385 : SAL_INFO("canvas.ogl", BOOST_CURRENT_FUNCTION );
386 0 : }
387 :
388 0 : void SpriteDeviceHelper::show( const ::rtl::Reference< CanvasCustomSprite >& xSprite )
389 : {
390 0 : maActiveSprites.insert(xSprite);
391 0 : }
392 :
393 0 : void SpriteDeviceHelper::hide( const ::rtl::Reference< CanvasCustomSprite >& xSprite )
394 : {
395 0 : maActiveSprites.erase(xSprite);
396 0 : }
397 :
398 0 : static void setupUniforms( unsigned int nProgramId,
399 : const ::basegfx::B2DHomMatrix& rTexTransform )
400 : {
401 : const GLint nTransformLocation = glGetUniformLocation(nProgramId,
402 0 : "m_transform" );
403 : // OGL is column-major
404 : float aTexTransform[] =
405 : {
406 0 : float(rTexTransform.get(0,0)), float(rTexTransform.get(1,0)),
407 0 : float(rTexTransform.get(0,1)), float(rTexTransform.get(1,1)),
408 0 : float(rTexTransform.get(0,2)), float(rTexTransform.get(1,2))
409 0 : };
410 0 : glUniformMatrix3x2fv(nTransformLocation,1,false,aTexTransform);
411 0 : }
412 :
413 0 : static void setupUniforms( unsigned int nProgramId,
414 : const rendering::ARGBColor* pColors,
415 : const uno::Sequence< double >& rStops,
416 : const ::basegfx::B2DHomMatrix& rTexTransform )
417 : {
418 0 : glUseProgram(nProgramId);
419 :
420 : GLuint nColorsTexture;
421 0 : glActiveTexture(GL_TEXTURE0);
422 0 : glGenTextures(1, &nColorsTexture);
423 0 : glBindTexture(GL_TEXTURE_1D, nColorsTexture);
424 :
425 0 : const sal_Int32 nColors=rStops.getLength();
426 0 : glTexImage1D( GL_TEXTURE_1D, 0, GL_RGBA, nColors, 0, GL_RGBA, GL_DOUBLE, pColors );
427 0 : glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
428 0 : glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
429 :
430 : GLuint nStopsTexture;
431 0 : glActiveTexture(GL_TEXTURE1);
432 0 : glGenTextures(1, &nStopsTexture);
433 0 : glBindTexture(GL_TEXTURE_1D, nStopsTexture);
434 :
435 0 : glTexImage1D( GL_TEXTURE_1D, 0, GL_ALPHA, nColors, 0, GL_ALPHA, GL_DOUBLE, rStops.getConstArray() );
436 0 : glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
437 0 : glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
438 :
439 : const GLint nColorArrayLocation = glGetUniformLocation(nProgramId,
440 0 : "t_colorArray4d" );
441 0 : glUniform1i( nColorArrayLocation, 0 ); // unit 0
442 :
443 : const GLint nStopArrayLocation = glGetUniformLocation(nProgramId,
444 0 : "t_stopArray1d" );
445 0 : glUniform1i( nStopArrayLocation, 1 ); // unit 1
446 :
447 : const GLint nNumColorLocation = glGetUniformLocation(nProgramId,
448 0 : "i_nColors" );
449 0 : glUniform1i( nNumColorLocation, nColors-1 );
450 :
451 0 : setupUniforms(nProgramId,rTexTransform);
452 0 : }
453 :
454 0 : static void setupUniforms( unsigned int nProgramId,
455 : const rendering::ARGBColor& rStartColor,
456 : const rendering::ARGBColor& rEndColor,
457 : const ::basegfx::B2DHomMatrix& rTexTransform )
458 : {
459 0 : glUseProgram(nProgramId);
460 :
461 : const GLint nStartColorLocation = glGetUniformLocation(nProgramId,
462 0 : "v_startColor4d" );
463 : glUniform4f(nStartColorLocation,
464 : rStartColor.Red,
465 : rStartColor.Green,
466 : rStartColor.Blue,
467 0 : rStartColor.Alpha);
468 :
469 : const GLint nEndColorLocation = glGetUniformLocation(nProgramId,
470 0 : "v_endColor4d" );
471 : glUniform4f(nEndColorLocation,
472 : rEndColor.Red,
473 : rEndColor.Green,
474 : rEndColor.Blue,
475 0 : rEndColor.Alpha);
476 :
477 0 : setupUniforms(nProgramId,rTexTransform);
478 0 : }
479 :
480 0 : void SpriteDeviceHelper::useLinearGradientShader( const rendering::ARGBColor* pColors,
481 : const uno::Sequence< double >& rStops,
482 : const ::basegfx::B2DHomMatrix& rTexTransform )
483 : {
484 0 : if( rStops.getLength() > 2 )
485 0 : setupUniforms(mnLinearMultiColorGradientProgram, pColors, rStops, rTexTransform);
486 : else
487 0 : setupUniforms(mnLinearTwoColorGradientProgram, pColors[0], pColors[1], rTexTransform);
488 0 : }
489 :
490 0 : void SpriteDeviceHelper::useRadialGradientShader( const rendering::ARGBColor* pColors,
491 : const uno::Sequence< double >& rStops,
492 : const ::basegfx::B2DHomMatrix& rTexTransform )
493 : {
494 0 : if( rStops.getLength() > 2 )
495 0 : setupUniforms(mnRadialMultiColorGradientProgram, pColors, rStops, rTexTransform);
496 : else
497 0 : setupUniforms(mnRadialTwoColorGradientProgram, pColors[0], pColors[1], rTexTransform);
498 0 : }
499 :
500 0 : void SpriteDeviceHelper::useRectangularGradientShader( const rendering::ARGBColor* pColors,
501 : const uno::Sequence< double >& rStops,
502 : const ::basegfx::B2DHomMatrix& rTexTransform )
503 : {
504 0 : if( rStops.getLength() > 2 )
505 0 : setupUniforms(mnRectangularMultiColorGradientProgram, pColors, rStops, rTexTransform);
506 : else
507 0 : setupUniforms(mnRectangularTwoColorGradientProgram, pColors[0], pColors[1], rTexTransform);
508 0 : }
509 :
510 0 : bool SpriteDeviceHelper::activateWindowContext()
511 : {
512 0 : maContext.makeCurrent();
513 0 : return true;
514 : }
515 :
516 : namespace
517 : {
518 :
519 : class BufferContextImpl : public IBufferContext
520 : {
521 : ::basegfx::B2IVector maSize;
522 : GLuint mnFrambufferId;
523 : GLuint mnDepthId;
524 : GLuint mnTextureId;
525 :
526 0 : virtual bool startBufferRendering() SAL_OVERRIDE
527 : {
528 0 : glBindFramebuffer(GL_FRAMEBUFFER, mnFrambufferId);
529 0 : return true;
530 : }
531 :
532 0 : virtual bool endBufferRendering() SAL_OVERRIDE
533 : {
534 0 : glBindFramebuffer(GL_FRAMEBUFFER, 0);
535 0 : return true;
536 : }
537 :
538 0 : virtual GLuint getTextureId() SAL_OVERRIDE
539 : {
540 0 : return mnTextureId;
541 : }
542 :
543 : public:
544 0 : explicit BufferContextImpl(const ::basegfx::B2IVector& rSize) :
545 : maSize(rSize),
546 : mnFrambufferId(0),
547 : mnDepthId(0),
548 0 : mnTextureId(0)
549 : {
550 0 : OpenGLHelper::createFramebuffer(maSize.getX(), maSize.getY(), mnFrambufferId,
551 0 : mnDepthId, mnTextureId, false);
552 0 : }
553 :
554 0 : virtual ~BufferContextImpl()
555 0 : {
556 0 : glDeleteTextures(1, &mnTextureId);
557 0 : glDeleteRenderbuffers(1, &mnDepthId);
558 0 : glDeleteFramebuffers(1, &mnFrambufferId);
559 0 : }
560 : };
561 : }
562 :
563 0 : IBufferContextSharedPtr SpriteDeviceHelper::createBufferContext(const ::basegfx::B2IVector& rSize) const
564 : {
565 0 : return IBufferContextSharedPtr(new BufferContextImpl(rSize));
566 : }
567 :
568 0 : TextureCache& SpriteDeviceHelper::getTextureCache() const
569 : {
570 0 : return *mpTextureCache;
571 : }
572 0 : }
573 :
574 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|