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 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "openglgdiimpl.hxx"
21 :
22 : #include <vcl/gradient.hxx>
23 : #include <salframe.hxx>
24 : #include "salvd.hxx"
25 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
26 : #include <basegfx/polygon/b2dlinegeometry.hxx>
27 : #include <basegfx/polygon/b2dpolygontools.hxx>
28 : #include <basegfx/polygon/b2dpolygontriangulator.hxx>
29 : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
30 : #include <basegfx/polygon/b2dtrapezoid.hxx>
31 :
32 : #include <vcl/opengl/OpenGLHelper.hxx>
33 : #include "salgdi.hxx"
34 : #include "svdata.hxx"
35 : #include "opengl/salbmp.hxx"
36 :
37 : #include <vector>
38 :
39 0 : OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvider *pProvider)
40 : : mpContext(0)
41 : , mrParent(rParent)
42 : , mpProvider(pProvider)
43 : , mpFramebuffer(NULL)
44 : , mpProgram(NULL)
45 : , mbUseScissor(false)
46 : , mbUseStencil(false)
47 : , mbOffscreen(false)
48 : , mnLineColor(SALCOLOR_NONE)
49 : , mnFillColor(SALCOLOR_NONE)
50 : #ifdef DBG_UTIL
51 : , mProgramIsSolidColor(false)
52 : #endif
53 : , mProgramSolidColor(SALCOLOR_NONE)
54 0 : , mProgramSolidTransparency(0.0)
55 : {
56 0 : }
57 :
58 0 : OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
59 : {
60 0 : ReleaseContext();
61 0 : }
62 :
63 0 : OpenGLContext* OpenGLSalGraphicsImpl::GetOpenGLContext()
64 : {
65 0 : if( !AcquireContext() )
66 0 : return NULL;
67 0 : return mpContext;
68 : }
69 :
70 0 : OpenGLContext* OpenGLSalGraphicsImpl::GetDefaultContext()
71 : {
72 0 : return ImplGetDefaultWindow()->GetGraphics()->GetOpenGLContext();
73 : }
74 :
75 0 : bool OpenGLSalGraphicsImpl::AcquireContext( )
76 : {
77 0 : ImplSVData* pSVData = ImplGetSVData();
78 :
79 0 : if( mpContext )
80 : {
81 0 : if( mpContext->isInitialized() )
82 0 : return true;
83 : #ifdef DBG_UTIL
84 : mpContext->DeRef(this);
85 : #else
86 0 : mpContext->DeRef();
87 : #endif
88 : }
89 :
90 :
91 0 : OpenGLContext* pContext = pSVData->maGDIData.mpLastContext;
92 0 : while( pContext )
93 : {
94 : // check if this context can be used by this SalGraphicsImpl instance
95 0 : if( UseContext( pContext ) )
96 0 : break;
97 0 : pContext = pContext->mpPrevContext;
98 : }
99 :
100 0 : if( pContext )
101 : {
102 : #ifdef DBG_UTIL
103 : pContext->AddRef(this);
104 : #else
105 0 : pContext->AddRef();
106 : #endif
107 : }
108 : else
109 0 : pContext = mbOffscreen ? GetDefaultContext() : CreateWinContext();
110 :
111 0 : mpContext = pContext;
112 0 : return (mpContext != NULL);
113 : }
114 :
115 0 : bool OpenGLSalGraphicsImpl::ReleaseContext()
116 : {
117 0 : if( mpContext )
118 : {
119 : #ifdef DBG_UTIL
120 : mpContext->DeRef(this);
121 : #else
122 0 : mpContext->DeRef();
123 : #endif
124 : }
125 0 : mpContext = NULL;
126 0 : return true;
127 : }
128 :
129 0 : void OpenGLSalGraphicsImpl::Init()
130 : {
131 0 : mbOffscreen = IsOffscreen();
132 :
133 : // check if we can simply re-use the same context
134 0 : if( mpContext )
135 : {
136 0 : if( !UseContext( mpContext ) )
137 0 : ReleaseContext();
138 : }
139 :
140 : // reset the offscreen texture
141 0 : if( !mbOffscreen ||
142 0 : maOffscreenTex.GetWidth() != GetWidth() ||
143 0 : maOffscreenTex.GetHeight() != GetHeight() )
144 : {
145 0 : if( mpContext ) // valid context
146 0 : mpContext->ReleaseFramebuffer( maOffscreenTex );
147 0 : maOffscreenTex = OpenGLTexture();
148 : }
149 0 : }
150 :
151 0 : void OpenGLSalGraphicsImpl::PreDraw()
152 : {
153 0 : if( !AcquireContext() )
154 : {
155 : SAL_WARN( "vcl.opengl", "Couldn't acquire context" );
156 0 : return;
157 : }
158 :
159 0 : mpContext->makeCurrent();
160 0 : CHECK_GL_ERROR();
161 :
162 0 : if( !mbOffscreen )
163 0 : mpContext->AcquireDefaultFramebuffer();
164 : else
165 0 : CheckOffscreenTexture();
166 0 : CHECK_GL_ERROR();
167 :
168 0 : glViewport( 0, 0, GetWidth(), GetHeight() );
169 0 : ImplInitClipRegion();
170 :
171 0 : CHECK_GL_ERROR();
172 : }
173 :
174 0 : void OpenGLSalGraphicsImpl::PostDraw()
175 : {
176 0 : if( !mbOffscreen && mpContext->mnPainting == 0 )
177 0 : glFlush();
178 0 : if( mbUseScissor )
179 0 : glDisable( GL_SCISSOR_TEST );
180 0 : if( mbUseStencil )
181 0 : glDisable( GL_STENCIL_TEST );
182 0 : if( mpProgram )
183 : {
184 0 : mpProgram->Clean();
185 0 : mpProgram = NULL;
186 : #ifdef DBG_UTIL
187 : mProgramIsSolidColor = false;
188 : #endif
189 : }
190 :
191 0 : CHECK_GL_ERROR();
192 0 : }
193 :
194 0 : void OpenGLSalGraphicsImpl::freeResources()
195 : {
196 : // TODO Delete shaders, programs and textures if not shared
197 0 : if( mbOffscreen && mpContext && mpContext->isInitialized() )
198 : {
199 0 : mpContext->makeCurrent();
200 0 : mpContext->ReleaseFramebuffer( maOffscreenTex );
201 : }
202 0 : ReleaseContext();
203 0 : }
204 :
205 0 : void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMask )
206 : {
207 0 : glEnable( GL_STENCIL_TEST );
208 0 : glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
209 0 : glStencilMask( nMask );
210 0 : glStencilFunc( GL_NEVER, nMask, 0xFF );
211 0 : glStencilOp( GL_REPLACE, GL_KEEP, GL_KEEP );
212 :
213 0 : glClear( GL_STENCIL_BUFFER_BIT );
214 0 : if( UseSolid( MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) ) )
215 : {
216 0 : if( rClip.getRegionBand() )
217 0 : DrawRegionBand( *rClip.getRegionBand() );
218 : else
219 0 : DrawPolyPolygon( rClip.GetAsB2DPolyPolygon(), true );
220 : }
221 :
222 0 : glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
223 0 : glStencilMask( 0x00 );
224 0 : glDisable( GL_STENCIL_TEST );
225 :
226 0 : CHECK_GL_ERROR();
227 0 : }
228 :
229 0 : void OpenGLSalGraphicsImpl::ImplInitClipRegion()
230 : {
231 : // make sure the context has the right clipping set
232 0 : if( maClipRegion != mpContext->maClipRegion )
233 : {
234 0 : mpContext->maClipRegion = maClipRegion;
235 0 : if( maClipRegion.IsRectangle() )
236 : {
237 0 : Rectangle aRect( maClipRegion.GetBoundRect() );
238 0 : glScissor( aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth() + 1, aRect.GetHeight() + 1 );
239 : }
240 0 : else if( !maClipRegion.IsEmpty() )
241 : {
242 0 : ImplSetClipBit( maClipRegion, 0x01 );
243 : }
244 : }
245 :
246 0 : if( mbUseScissor )
247 0 : glEnable( GL_SCISSOR_TEST );
248 0 : if( mbUseStencil )
249 : {
250 0 : glStencilFunc( GL_EQUAL, 1, 0x1 );
251 0 : glEnable( GL_STENCIL_TEST );
252 : }
253 :
254 0 : CHECK_GL_ERROR();
255 0 : }
256 :
257 0 : const vcl::Region& OpenGLSalGraphicsImpl::getClipRegion() const
258 : {
259 0 : return maClipRegion;
260 : }
261 :
262 0 : bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
263 : {
264 : SAL_INFO( "vcl.opengl", "::setClipRegion " << rClip );
265 0 : maClipRegion = rClip;
266 :
267 0 : mbUseStencil = false;
268 0 : mbUseScissor = false;
269 0 : if( maClipRegion.IsRectangle() )
270 0 : mbUseScissor = true;
271 0 : else if ( !maClipRegion.IsEmpty() )
272 0 : mbUseStencil = true;
273 :
274 0 : return true;
275 : }
276 :
277 : // set the clip region to empty
278 0 : void OpenGLSalGraphicsImpl::ResetClipRegion()
279 : {
280 : SAL_INFO( "vcl.opengl", "::ResetClipRegion" );
281 0 : maClipRegion.SetEmpty();
282 0 : mbUseScissor = false;
283 0 : mbUseStencil = false;
284 0 : }
285 :
286 : // get the depth of the device
287 0 : sal_uInt16 OpenGLSalGraphicsImpl::GetBitCount() const
288 : {
289 0 : return 32;
290 : }
291 :
292 : // get the width of the device
293 0 : long OpenGLSalGraphicsImpl::GetGraphicsWidth() const
294 : {
295 0 : return GetWidth();
296 : }
297 :
298 : // set the line color to transparent (= don't draw lines)
299 0 : void OpenGLSalGraphicsImpl::SetLineColor()
300 : {
301 0 : if( mnLineColor != SALCOLOR_NONE )
302 : {
303 0 : mnLineColor = SALCOLOR_NONE;
304 : }
305 0 : }
306 :
307 : // set the line color to a specific color
308 0 : void OpenGLSalGraphicsImpl::SetLineColor( SalColor nSalColor )
309 : {
310 0 : if( mnLineColor != nSalColor )
311 : {
312 0 : mnLineColor = nSalColor;
313 : }
314 0 : }
315 :
316 : // set the fill color to transparent (= don't fill)
317 0 : void OpenGLSalGraphicsImpl::SetFillColor()
318 : {
319 0 : if( mnFillColor != SALCOLOR_NONE )
320 : {
321 0 : mnFillColor = SALCOLOR_NONE;
322 : }
323 0 : }
324 :
325 : // set the fill color to a specific color, shapes will be
326 : // filled accordingly
327 0 : void OpenGLSalGraphicsImpl::SetFillColor( SalColor nSalColor )
328 : {
329 0 : if( mnFillColor != nSalColor )
330 : {
331 0 : mnFillColor = nSalColor;
332 : }
333 0 : }
334 :
335 : // enable/disable XOR drawing
336 0 : void OpenGLSalGraphicsImpl::SetXORMode( bool /*bSet*/, bool /*bInvertOnly*/ )
337 : {
338 0 : }
339 :
340 : // set line color for raster operations
341 0 : void OpenGLSalGraphicsImpl::SetROPLineColor( SalROPColor /*nROPColor*/ )
342 : {
343 0 : }
344 :
345 : // set fill color for raster operations
346 0 : void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ )
347 : {
348 0 : }
349 :
350 0 : bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
351 : {
352 0 : if( !maOffscreenTex )
353 0 : maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
354 :
355 0 : if( !maOffscreenTex.IsUnique() )
356 : {
357 0 : GLfloat fWidth = GetWidth();
358 0 : GLfloat fHeight = GetHeight();
359 0 : SalTwoRect aPosAry(0, 0, fWidth, fHeight, 0,0, fWidth, fHeight);
360 :
361 : // TODO: lfrb: User GL_ARB_copy_image?
362 0 : OpenGLTexture aNewTex = OpenGLTexture( GetWidth(), GetHeight() );
363 0 : mpFramebuffer = mpContext->AcquireFramebuffer( aNewTex );
364 0 : DrawTexture( maOffscreenTex, aPosAry );
365 0 : maOffscreenTex = aNewTex;
366 : }
367 : else
368 : {
369 0 : mpFramebuffer = mpContext->AcquireFramebuffer( maOffscreenTex );
370 : }
371 :
372 0 : CHECK_GL_ERROR();
373 0 : return true;
374 : }
375 :
376 0 : bool OpenGLSalGraphicsImpl::UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble )
377 : {
378 0 : if( mpProgram != NULL )
379 0 : mpProgram->Clean();
380 0 : mpProgram = mpContext->UseProgram( rVertexShader, rFragmentShader, preamble );
381 : #ifdef DBG_UTIL
382 : mProgramIsSolidColor = false; // UseSolid() will set to true if needed
383 : #endif
384 0 : return ( mpProgram != NULL );
385 : }
386 :
387 0 : bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor, sal_uInt8 nTransparency )
388 : {
389 0 : if( nColor == SALCOLOR_NONE )
390 0 : return false;
391 0 : if( !UseProgram( "dumbVertexShader", "solidFragmentShader" ) )
392 0 : return false;
393 0 : mpProgram->SetColor( "color", nColor, nTransparency );
394 : #ifdef DBG_UTIL
395 : mProgramIsSolidColor = true;
396 : #endif
397 0 : mProgramSolidColor = nColor;
398 0 : mProgramSolidTransparency = nTransparency / 100.0;
399 0 : return true;
400 : }
401 :
402 0 : bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor, double fTransparency )
403 : {
404 0 : if( nColor == SALCOLOR_NONE )
405 0 : return false;
406 0 : if( !UseProgram( "dumbVertexShader", "solidFragmentShader" ) )
407 0 : return false;
408 0 : mpProgram->SetColorf( "color", nColor, fTransparency );
409 : #ifdef DBG_UTIL
410 : mProgramIsSolidColor = true;
411 : #endif
412 0 : mProgramSolidColor = nColor;
413 0 : mProgramSolidTransparency = fTransparency;
414 0 : return true;
415 : }
416 :
417 0 : bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor )
418 : {
419 0 : return UseSolid( nColor, 0.0f );
420 : }
421 :
422 : // Like UseSolid(), but sets up for AA drawing, which uses gradients to create the AA.
423 0 : bool OpenGLSalGraphicsImpl::UseSolidAA( SalColor nColor, double fTransparency )
424 : {
425 0 : if( nColor == SALCOLOR_NONE )
426 0 : return false;
427 0 : if( !mrParent.getAntiAliasB2DDraw())
428 0 : return UseSolid( nColor );
429 0 : if( !UseProgram( "textureVertexShader", "linearGradientFragmentShader" ) )
430 0 : return false;
431 0 : mpProgram->SetColorf( "start_color", nColor, fTransparency );
432 0 : mpProgram->SetColorf( "end_color", nColor, 1.0f );
433 0 : return true;
434 : }
435 :
436 0 : bool OpenGLSalGraphicsImpl::UseSolidAA( SalColor nColor )
437 : {
438 0 : return UseSolidAA( nColor, 0.0 );
439 : }
440 :
441 0 : bool OpenGLSalGraphicsImpl::UseInvert()
442 : {
443 0 : if( !UseSolid( MAKE_SALCOLOR( 255, 255, 255 ) ) )
444 0 : return false;
445 0 : mpProgram->SetBlendMode( GL_ONE_MINUS_DST_COLOR, GL_ZERO );
446 0 : return true;
447 : }
448 :
449 0 : void OpenGLSalGraphicsImpl::DrawPoint( long nX, long nY )
450 : {
451 : GLfloat pPoint[2];
452 :
453 0 : pPoint[0] = 2 * nX / GetWidth() - 1.0f;
454 0 : pPoint[1] = 1.0f - 2 * nY / GetHeight();
455 :
456 0 : mpProgram->SetVertices( pPoint );
457 0 : glDrawArrays( GL_POINTS, 0, 1 );
458 :
459 0 : CHECK_GL_ERROR();
460 0 : }
461 :
462 0 : void OpenGLSalGraphicsImpl::DrawLine( double nX1, double nY1, double nX2, double nY2 )
463 : {
464 : GLfloat pPoints[4];
465 :
466 0 : pPoints[0] = (2 * nX1) / GetWidth() - 1.0;
467 0 : pPoints[1] = 1.0f - 2 * nY1 / GetHeight();
468 0 : pPoints[2] = (2 * nX2) / GetWidth() - 1.0;;
469 0 : pPoints[3] = 1.0f - 2 * nY2 / GetHeight();
470 :
471 0 : mpProgram->SetVertices( pPoints );
472 0 : glDrawArrays( GL_LINES, 0, 2 );
473 :
474 0 : CHECK_GL_ERROR();
475 0 : }
476 :
477 0 : void OpenGLSalGraphicsImpl::DrawLineAA( double nX1, double nY1, double nX2, double nY2 )
478 : {
479 0 : if( !mrParent.getAntiAliasB2DDraw())
480 0 : return DrawLine( nX1, nY1, nX2, nY2 );
481 :
482 0 : if( nX1 == nX2 || nY1 == nY2 )
483 : { // Horizontal/vertical, no need for AA, both points have normal color.
484 : GLfloat pPoints[4];
485 :
486 0 : pPoints[0] = (2 * nX1) / GetWidth() - 1.0;
487 0 : pPoints[1] = 1.0f - 2 * nY1 / GetHeight();
488 0 : pPoints[2] = (2 * nX2) / GetWidth() - 1.0;;
489 0 : pPoints[3] = 1.0f - 2 * nY2 / GetHeight();
490 :
491 0 : mpProgram->SetVertices( pPoints );
492 : // Still set up for the trivial "gradients", because presumably UseSolidAA() has been called.
493 0 : GLfloat aTexCoord[4] = { 0, 1, 1, 1 };
494 0 : mpProgram->SetTextureCoord( aTexCoord );
495 :
496 0 : glDrawArrays( GL_LINES, 0, 2 );
497 0 : return;
498 : }
499 0 : ImplDrawLineAA( nX1, nY1, nX2, nY2 );
500 :
501 0 : CHECK_GL_ERROR();
502 : }
503 :
504 0 : void OpenGLSalGraphicsImpl::ImplDrawLineAA( double nX1, double nY1, double nX2, double nY2, bool edge )
505 : {
506 : // Draw the line anti-aliased. Based on code with the following notice:
507 : /* Drawing nearly perfect 2D line segments in OpenGL
508 : * You can use this code however you want.
509 : * I just hope you to cite my name and the page of this technique:
510 : * http://artgrammer.blogspot.com/2011/05/drawing-nearly-perfect-2d-line-segments.html
511 : * http://www.codeproject.com/KB/openGL/gllinedraw.aspx
512 : *
513 : * Enjoy. Chris Tsang.*/
514 :
515 0 : double x1 = nX1;
516 0 : double y1 = nY1;
517 0 : double x2 = nX2;
518 0 : double y2 = nY2;
519 :
520 : // A special hack for drawing lines that are in fact AA edges of a shape. Make the line somewhat
521 : // wider, but (done further below) draw the entire width as a gradient. This would be wrong for a line
522 : // (too wide and seemingly less straight), but it makes the edges look smoother and the width difference
523 : // is almost unnoticeable.
524 0 : const double w = edge ? 1.4 : 1.0;
525 :
526 0 : double t(0.0);
527 0 : double R(0.0);
528 0 : double f = w - static_cast<int>(w);
529 : //determine parameters t,R
530 0 : if ( w>=0.0 && w<1.0 )
531 : {
532 0 : t=0.05;
533 0 : R=0.48+0.32*f;
534 : }
535 0 : else if ( w>=1.0 && w<2.0 )
536 : {
537 0 : t=0.05+f*0.33;
538 0 : R=0.768+0.312*f;
539 : }
540 0 : else if ( w>=2.0 && w<3.0 )
541 : {
542 0 : t=0.38+f*0.58;
543 0 : R=1.08;
544 : }
545 0 : else if ( w>=3.0 && w<4.0 )
546 : {
547 0 : t=0.96+f*0.48;
548 0 : R=1.08;
549 : }
550 0 : else if ( w>=4.0 && w<5.0 )
551 : {
552 0 : t=1.44+f*0.46;
553 0 : R=1.08;
554 : }
555 0 : else if ( w>=5.0 && w<6.0 )
556 : {
557 0 : t=1.9+f*0.6;
558 0 : R=1.08;
559 : }
560 0 : else if ( w>=6.0 )
561 : {
562 0 : double ff=w-6.0;
563 0 : t=2.5+ff*0.50;
564 0 : R=1.08;
565 : }
566 :
567 : //determine angle of the line to horizontal
568 0 : double tx=0,ty=0; //core thinkness of a line
569 0 : double Rx=0,Ry=0; //fading edge of a line
570 0 : double dx=x2-x1;
571 0 : double dy=y2-y1;
572 0 : if ( w < 3 )
573 : { //approximate to make things even faster
574 0 : double m=dy/dx;
575 : //and calculate tx,ty,Rx,Ry
576 0 : if ( m>-0.4142 && m<=0.4142)
577 : {
578 : // -22.5< angle <= 22.5, approximate to 0 (degree)
579 0 : tx=t*0.1; ty=t;
580 0 : Rx=R*0.6; Ry=R;
581 : }
582 0 : else if ( m>0.4142 && m<=2.4142)
583 : {
584 : // 22.5< angle <= 67.5, approximate to 45 (degree)
585 0 : tx=t*-0.7071; ty=t*0.7071;
586 0 : Rx=R*-0.7071; Ry=R*0.7071;
587 : }
588 0 : else if ( m>2.4142 || m<=-2.4142)
589 : {
590 : // 67.5 < angle <=112.5, approximate to 90 (degree)
591 0 : tx=t; ty=t*0.1;
592 0 : Rx=R; Ry=R*0.6;
593 : }
594 0 : else if ( m>-2.4142 && m<-0.4142)
595 : {
596 : // 112.5 < angle < 157.5, approximate to 135 (degree)
597 0 : tx=t*0.7071; ty=t*0.7071;
598 0 : Rx=R*0.7071; Ry=R*0.7071;
599 : }
600 : else
601 : assert( false );
602 : }
603 : else
604 : { //calculate to exact
605 0 : dx=y1-y2;
606 0 : dy=x2-x1;
607 0 : double L=sqrt(dx*dx+dy*dy);
608 0 : dx/=L;
609 0 : dy/=L;
610 0 : tx=t*dx; ty=t*dy;
611 0 : Rx=R*dx; Ry=R*dy;
612 : }
613 :
614 0 : if( edge )
615 : { // See above.
616 0 : Rx += tx;
617 0 : Ry += ty;
618 0 : tx = ty = 0;
619 : }
620 :
621 : GLfloat vertices[]=
622 : {
623 : #define convertX( x ) GLfloat( (2 * (x)) / GetWidth() - 1.0f)
624 : #define convertY( y ) GLfloat( 1.0f - (2 * (y)) / GetHeight())
625 0 : convertX(x1-tx-Rx), convertY(y1-ty-Ry), //fading edge1
626 0 : convertX(x2-tx-Rx), convertY(y2-ty-Ry),
627 0 : convertX(x1-tx),convertY(y1-ty), //core
628 0 : convertX(x2-tx),convertY(y2-ty),
629 0 : convertX(x1+tx),convertY(y1+ty),
630 0 : convertX(x2+tx),convertY(y2+ty),
631 0 : convertX(x1+tx+Rx), convertY(y1+ty+Ry), //fading edge2
632 0 : convertX(x2+tx+Rx), convertY(y2+ty+Ry)
633 : #undef convertX
634 : #undef convertY
635 0 : };
636 :
637 0 : GLfloat aTexCoord[16] = { 0, 0, 1, 0, 2, 1, 3, 1, 4, 1, 5, 1, 6, 0, 7, 0 };
638 0 : mpProgram->SetTextureCoord( aTexCoord );
639 0 : mpProgram->SetVertices( vertices );
640 0 : glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
641 :
642 0 : CHECK_GL_ERROR();
643 0 : }
644 :
645 0 : void OpenGLSalGraphicsImpl::DrawLines( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose )
646 : {
647 0 : for( int i = 0; i < int(nPoints) - 1; ++i )
648 0 : DrawLine( pPtAry[ i ].mnX, pPtAry[ i ].mnY, pPtAry[ i + 1 ].mnX, pPtAry[ i + 1 ].mnY );
649 0 : if( bClose )
650 0 : DrawLine( pPtAry[ nPoints - 1 ].mnX, pPtAry[ nPoints - 1 ].mnY, pPtAry[ 0 ].mnX, pPtAry[ 0 ].mnY );
651 0 : }
652 :
653 0 : void OpenGLSalGraphicsImpl::DrawLinesAA( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose )
654 : {
655 0 : for( int i = 0; i < int(nPoints) - 1; ++i )
656 0 : DrawLineAA( pPtAry[ i ].mnX, pPtAry[ i ].mnY, pPtAry[ i + 1 ].mnX, pPtAry[ i + 1 ].mnY );
657 0 : if( bClose )
658 0 : DrawLineAA( pPtAry[ nPoints - 1 ].mnX, pPtAry[ nPoints - 1 ].mnY, pPtAry[ 0 ].mnX, pPtAry[ 0 ].mnY );
659 0 : }
660 :
661 0 : void OpenGLSalGraphicsImpl::DrawEdgeAA( double nX1, double nY1, double nX2, double nY2 )
662 : {
663 : assert( mrParent.getAntiAliasB2DDraw());
664 0 : if( nX1 == nX2 || nY1 == nY2 )
665 0 : return; //horizontal/vertical, no need for AA
666 0 : ImplDrawLineAA( nX1, nY1, nX2, nY2, true );
667 : }
668 :
669 0 : void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry, bool blockAA )
670 : {
671 0 : std::vector<GLfloat> aVertices(nPoints * 2);
672 : sal_uInt32 i, j;
673 :
674 0 : for( i = 0, j = 0; i < nPoints; i++, j += 2 )
675 : {
676 0 : aVertices[j] = (2 * pPtAry[i].mnX) / GetWidth() - 1.0;
677 0 : aVertices[j+1] = 1.0 - (2 * pPtAry[i].mnY / GetHeight());
678 : }
679 :
680 0 : mpProgram->SetVertices( &aVertices[0] );
681 0 : glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
682 :
683 0 : if( !blockAA && mrParent.getAntiAliasB2DDraw())
684 : {
685 : // Make the edges antialiased by drawing the edge lines again with AA.
686 : // TODO: If transparent drawing is set up, drawing the lines themselves twice
687 : // may be a problem, if that is a real problem, the polygon areas itself needs to be
688 : // masked out for this or something.
689 : #ifdef DBG_UTIL
690 : assert( mProgramIsSolidColor );
691 : #endif
692 0 : SalColor lastSolidColor = mProgramSolidColor;
693 0 : double lastSolidTransparency = mProgramSolidTransparency;
694 0 : if( UseSolidAA( lastSolidColor, lastSolidTransparency ))
695 : {
696 0 : for( i = 0; i < nPoints; ++i )
697 : {
698 0 : const SalPoint& rPt1 = pPtAry[ i ];
699 0 : const SalPoint& rPt2 = pPtAry[ ( i + 1 ) % nPoints ];
700 0 : DrawEdgeAA( rPt1.mnX, rPt1.mnY, rPt2.mnX, rPt2.mnY );
701 : }
702 0 : UseSolid( lastSolidColor, lastSolidTransparency );
703 : }
704 : }
705 :
706 0 : CHECK_GL_ERROR();
707 0 : }
708 :
709 0 : void OpenGLSalGraphicsImpl::DrawConvexPolygon( const Polygon& rPolygon, bool blockAA )
710 : {
711 0 : sal_uInt16 nPoints = rPolygon.GetSize() - 1;
712 0 : std::vector<GLfloat> aVertices(nPoints * 2);
713 : sal_uInt32 i, j;
714 :
715 0 : for( i = 0, j = 0; i < nPoints; i++, j += 2 )
716 : {
717 0 : const Point& rPt = rPolygon.GetPoint( i );
718 0 : aVertices[j] = (2 * rPt.X()) / GetWidth() - 1.0;
719 0 : aVertices[j+1] = 1.0 - (2 * rPt.Y() / GetHeight());
720 : }
721 :
722 0 : mpProgram->SetVertices( &aVertices[0] );
723 0 : glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
724 :
725 0 : if( !blockAA && mrParent.getAntiAliasB2DDraw())
726 : {
727 : // Make the edges antialiased by drawing the edge lines again with AA.
728 : // TODO: If transparent drawing is set up, drawing the lines themselves twice
729 : // may be a problem, if that is a real problem, the polygon areas itself needs to be
730 : // masked out for this or something.
731 : #ifdef DBG_UTIL
732 : assert( mProgramIsSolidColor );
733 : #endif
734 0 : SalColor lastSolidColor = mProgramSolidColor;
735 0 : double lastSolidTransparency = mProgramSolidTransparency;
736 0 : if( UseSolidAA( lastSolidColor, lastSolidTransparency ))
737 : {
738 0 : for( i = 0; i < nPoints; ++i )
739 : {
740 0 : const Point& rPt1 = rPolygon.GetPoint( i );
741 0 : const Point& rPt2 = rPolygon.GetPoint(( i + 1 ) % nPoints );
742 0 : DrawEdgeAA( rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY());
743 : }
744 0 : UseSolid( lastSolidColor, lastSolidTransparency );
745 : }
746 : }
747 :
748 0 : CHECK_GL_ERROR();
749 0 : }
750 :
751 0 : void OpenGLSalGraphicsImpl::DrawTrapezoid( const basegfx::B2DTrapezoid& trapezoid, bool blockAA )
752 : {
753 0 : const basegfx::B2DPolygon& rPolygon = trapezoid.getB2DPolygon();
754 0 : sal_uInt16 nPoints = rPolygon.count();
755 0 : std::vector<GLfloat> aVertices(nPoints * 2);
756 : sal_uInt32 i, j;
757 :
758 0 : for( i = 0, j = 0; i < nPoints; i++, j += 2 )
759 : {
760 0 : const basegfx::B2DPoint& rPt = rPolygon.getB2DPoint( i );
761 0 : aVertices[j] = (2 * rPt.getX()) / GetWidth() - 1.0;
762 0 : aVertices[j+1] = 1.0 - (2 * rPt.getY() / GetHeight());
763 0 : }
764 :
765 0 : mpProgram->SetVertices( &aVertices[0] );
766 0 : glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
767 :
768 0 : if( !blockAA && mrParent.getAntiAliasB2DDraw())
769 : {
770 : // Make the edges antialiased by drawing the edge lines again with AA.
771 : // TODO: If transparent drawing is set up, drawing the lines themselves twice
772 : // may be a problem, if that is a real problem, the polygon areas itself needs to be
773 : // masked out for this or something.
774 : #ifdef DBG_UTIL
775 : assert( mProgramIsSolidColor );
776 : #endif
777 0 : SalColor lastSolidColor = mProgramSolidColor;
778 0 : double lastSolidTransparency = mProgramSolidTransparency;
779 0 : if( UseSolidAA( lastSolidColor, lastSolidTransparency ))
780 : {
781 0 : for( i = 0; i < nPoints; ++i )
782 : {
783 0 : const basegfx::B2DPoint& rPt1 = rPolygon.getB2DPoint( i );
784 0 : const basegfx::B2DPoint& rPt2 = rPolygon.getB2DPoint(( i + 1 ) % nPoints );
785 0 : DrawEdgeAA( rPt1.getX(), rPt1.getY(), rPt2.getX(), rPt2.getY());
786 0 : }
787 0 : UseSolid( lastSolidColor, lastSolidTransparency );
788 : }
789 : }
790 :
791 0 : CHECK_GL_ERROR();
792 0 : }
793 :
794 0 : void OpenGLSalGraphicsImpl::DrawRect( long nX, long nY, long nWidth, long nHeight )
795 : {
796 0 : long nX1( nX );
797 0 : long nY1( nY );
798 0 : long nX2( nX + nWidth );
799 0 : long nY2( nY + nHeight );
800 : const SalPoint aPoints[] = { { nX1, nY2 }, { nX1, nY1 },
801 0 : { nX2, nY1 }, { nX2, nY2 }};
802 :
803 0 : DrawConvexPolygon( 4, aPoints, true );
804 0 : }
805 :
806 0 : void OpenGLSalGraphicsImpl::DrawRect( const Rectangle& rRect )
807 : {
808 0 : long nX1( rRect.Left() );
809 0 : long nY1( rRect.Top() );
810 0 : long nX2( rRect.Right() );
811 0 : long nY2( rRect.Bottom() );
812 : const SalPoint aPoints[] = { { nX1, nY2 }, { nX1, nY1 },
813 0 : { nX2, nY1 }, { nX2, nY2 }};
814 :
815 0 : DrawConvexPolygon( 4, aPoints, true );
816 0 : }
817 :
818 0 : void OpenGLSalGraphicsImpl::DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
819 : {
820 0 : ::basegfx::B2DPolygon aPolygon;
821 :
822 0 : for( sal_uInt32 i = 0; i < nPoints; i++ )
823 0 : aPolygon.append( ::basegfx::B2DPoint( pPtAry[i].mnX, pPtAry[i].mnY ) );
824 0 : aPolygon.setClosed( true );
825 :
826 0 : if( ::basegfx::tools::isConvex( aPolygon ) )
827 : {
828 0 : if( nPoints > 2L )
829 0 : DrawConvexPolygon( nPoints, pPtAry );
830 : }
831 : else
832 : {
833 0 : const ::basegfx::B2DPolyPolygon aPolyPolygon( aPolygon );
834 0 : DrawPolyPolygon( aPolyPolygon );
835 0 : }
836 0 : }
837 :
838 0 : void OpenGLSalGraphicsImpl::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon, bool blockAA )
839 : {
840 0 : const ::basegfx::B2DPolyPolygon& aSimplePolyPolygon = ::basegfx::tools::solveCrossovers( rPolyPolygon );
841 0 : basegfx::B2DTrapezoidVector aB2DTrapVector;
842 0 : basegfx::tools::trapezoidSubdivide( aB2DTrapVector, aSimplePolyPolygon );
843 : // draw tesselation result
844 0 : if( aB2DTrapVector.size())
845 : {
846 0 : for( size_t i = 0; i < aB2DTrapVector.size(); ++i )
847 0 : DrawTrapezoid( aB2DTrapVector[ i ], blockAA );
848 0 : }
849 0 : }
850 :
851 0 : void OpenGLSalGraphicsImpl::DrawRegionBand( const RegionBand& rRegion )
852 : {
853 0 : RectangleVector aRects;
854 0 : std::vector<GLfloat> aVertices;
855 0 : rRegion.GetRegionRectangles( aRects );
856 :
857 0 : if( aRects.empty() )
858 0 : return;
859 :
860 : #define ADD_VERTICE(pt) \
861 : aVertices.push_back( 2 * pt.X() / GetWidth() - 1.0 ); \
862 : aVertices.push_back( 1.0 - (2 * pt.Y() / GetHeight()) );
863 :
864 0 : for( size_t i = 0; i < aRects.size(); ++i )
865 : {
866 0 : aRects[i].Bottom() += 1;
867 0 : aRects[i].Right() += 1;
868 0 : ADD_VERTICE( aRects[i].TopLeft() );
869 0 : ADD_VERTICE( aRects[i].TopRight() );
870 0 : ADD_VERTICE( aRects[i].BottomLeft() );
871 0 : ADD_VERTICE( aRects[i].BottomLeft() );
872 0 : ADD_VERTICE( aRects[i].TopRight() );
873 0 : ADD_VERTICE( aRects[i].BottomRight() );
874 : }
875 :
876 : #undef ADD_VERTICE
877 :
878 0 : mpProgram->SetVertices( &aVertices[0] );
879 0 : glDrawArrays( GL_TRIANGLES, 0, aVertices.size() / 2 );
880 :
881 0 : CHECK_GL_ERROR();
882 : }
883 :
884 0 : void OpenGLSalGraphicsImpl::DrawTextureRect( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted )
885 : {
886 : GLfloat aTexCoord[8];
887 0 : rTexture.GetCoord( aTexCoord, rPosAry, bInverted );
888 0 : mpProgram->SetTextureCoord( aTexCoord );
889 0 : DrawRect( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight );
890 0 : }
891 :
892 0 : void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& pPosAry, bool bInverted )
893 : {
894 0 : if( !UseProgram( "textureVertexShader", "textureFragmentShader" ) )
895 0 : return;
896 0 : mpProgram->SetTexture( "sampler", rTexture );
897 0 : DrawTextureRect( rTexture, pPosAry, bInverted );
898 0 : mpProgram->Clean();
899 : }
900 :
901 0 : void OpenGLSalGraphicsImpl::DrawTransformedTexture(
902 : OpenGLTexture& rTexture,
903 : OpenGLTexture& rMask,
904 : const basegfx::B2DPoint& rNull,
905 : const basegfx::B2DPoint& rX,
906 : const basegfx::B2DPoint& rY )
907 : {
908 : GLfloat aVertices[8] = {
909 0 : 0, (float) rTexture.GetHeight(), 0, 0,
910 0 : (float) rTexture.GetWidth(), 0, (float) rTexture.GetWidth(), (float) rTexture.GetHeight() };
911 : GLfloat aTexCoord[8];
912 :
913 : // If downscaling at a higher scale ratio, use the area scaling algorithm rather
914 : // than plain OpenGL's scaling, for better results.
915 : // See OpenGLSalBitmap::ImplScaleArea().
916 0 : double ixscale = rTexture.GetWidth() / fabs( rX.getX() - rNull.getX());
917 0 : double iyscale = rTexture.GetHeight() / fabs( rY.getY() - rNull.getY());
918 0 : bool areaScaling = false;
919 0 : bool fastAreaScaling = false;
920 0 : OUString textureFragmentShader;
921 0 : if( ixscale >= 2 && iyscale >= 2 ) // Downscaling to 50% or less? (inverted scale ratios)
922 : {
923 0 : areaScaling = true;
924 0 : fastAreaScaling = ( ixscale == int( ixscale ) && iyscale == int( iyscale ));
925 : // The generic case has arrays only up to 100 ratio downscaling, which is hopefully enough
926 : // in practice, but protect against buffer overflows in case such an extreme case happens
927 : // (and in such case the precision of the generic algorithm probably doesn't matter anyway).
928 0 : if( ixscale > 100 || iyscale > 100 )
929 0 : fastAreaScaling = true;
930 0 : if( fastAreaScaling )
931 0 : textureFragmentShader = "areaScaleFastFragmentShader";
932 : else
933 0 : textureFragmentShader = "areaScaleFragmentShader";
934 : }
935 :
936 0 : if( rMask )
937 : {
938 0 : if( !UseProgram( "transformedTextureVertexShader",
939 0 : textureFragmentShader.isEmpty() ? "maskedTextureFragmentShader" : textureFragmentShader,
940 0 : "#define MASKED" ) )
941 0 : return;
942 0 : mpProgram->SetTexture( "mask", rMask );
943 0 : rMask.SetFilter( GL_LINEAR );
944 0 : mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
945 : }
946 : else
947 : {
948 0 : if( !UseProgram( "transformedTextureVertexShader",
949 0 : textureFragmentShader.isEmpty() ? "textureFragmentShader" : textureFragmentShader ) )
950 0 : return;
951 : }
952 :
953 0 : int mnWidth = rTexture.GetWidth();
954 0 : int mnHeight = rTexture.GetHeight();
955 0 : if(areaScaling )
956 : {
957 : // From OpenGLSalBitmap::ImplScaleArea().
958 0 : if (fastAreaScaling && mnWidth && mnHeight)
959 : {
960 0 : mpProgram->SetUniform1i( "xscale", ixscale );
961 0 : mpProgram->SetUniform1i( "yscale", iyscale );
962 0 : mpProgram->SetUniform1f( "xstep", 1.0 / mnWidth );
963 0 : mpProgram->SetUniform1f( "ystep", 1.0 / mnHeight );
964 0 : mpProgram->SetUniform1f( "ratio", 1.0 / ( ixscale * iyscale ));
965 : }
966 0 : else if (mnHeight > 1 && mnWidth > 1)
967 : {
968 0 : mpProgram->SetUniform1f( "xscale", ixscale );
969 0 : mpProgram->SetUniform1f( "yscale", iyscale );
970 0 : mpProgram->SetUniform1i( "swidth", mnWidth );
971 0 : mpProgram->SetUniform1i( "sheight", mnHeight );
972 : // For converting between <0,mnWidth-1> and <0.0,1.0> coordinate systems.
973 0 : mpProgram->SetUniform1f( "xsrcconvert", 1.0 / ( mnWidth - 1 ));
974 0 : mpProgram->SetUniform1f( "ysrcconvert", 1.0 / ( mnHeight - 1 ));
975 0 : mpProgram->SetUniform1f( "xdestconvert", 1.0 * (( mnWidth / ixscale ) - 1 ));
976 0 : mpProgram->SetUniform1f( "ydestconvert", 1.0 * (( mnHeight / iyscale ) - 1 ));
977 : }
978 : }
979 :
980 0 : mpProgram->SetUniform2f( "viewport", GetWidth(), GetHeight() );
981 0 : mpProgram->SetTransform( "transform", rTexture, rNull, rX, rY );
982 0 : rTexture.GetWholeCoord( aTexCoord );
983 0 : mpProgram->SetTexture( "sampler", rTexture );
984 0 : rTexture.SetFilter( GL_LINEAR );
985 0 : mpProgram->SetTextureCoord( aTexCoord );
986 0 : mpProgram->SetVertices( &aVertices[0] );
987 0 : glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
988 0 : mpProgram->Clean();
989 :
990 0 : CHECK_GL_ERROR();
991 : }
992 :
993 0 : void OpenGLSalGraphicsImpl::DrawAlphaTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted, bool bPremultiplied )
994 : {
995 0 : if( !UseProgram( "textureVertexShader", "textureFragmentShader" ) )
996 0 : return;
997 0 : mpProgram->SetTexture( "sampler", rTexture );
998 : mpProgram->SetBlendMode( bPremultiplied ? GL_ONE : GL_SRC_ALPHA,
999 0 : GL_ONE_MINUS_SRC_ALPHA );
1000 0 : DrawTextureRect( rTexture, rPosAry, bInverted );
1001 0 : mpProgram->Clean();
1002 : }
1003 :
1004 0 : void OpenGLSalGraphicsImpl::DrawTextureDiff( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry, bool bInverted )
1005 : {
1006 0 : if( !UseProgram( "textureVertexShader", "diffTextureFragmentShader" ) )
1007 0 : return;
1008 0 : mpProgram->SetTexture( "texture", rTexture );
1009 0 : mpProgram->SetTexture( "mask", rMask );
1010 0 : mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1011 0 : DrawTextureRect( rTexture, rPosAry, bInverted );
1012 0 : mpProgram->Clean();
1013 : }
1014 :
1015 0 : void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& pPosAry )
1016 : {
1017 0 : if( !UseProgram( "textureVertexShader", "maskedTextureFragmentShader" ) )
1018 0 : return;
1019 0 : mpProgram->SetTexture( "sampler", rTexture );
1020 0 : mpProgram->SetTexture( "mask", rMask );
1021 0 : mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1022 0 : DrawTextureRect( rTexture, pPosAry );
1023 0 : mpProgram->Clean();
1024 : }
1025 :
1026 0 : void OpenGLSalGraphicsImpl::DrawBlendedTexture( OpenGLTexture& rTexture, OpenGLTexture& rMask, OpenGLTexture& rAlpha, const SalTwoRect& rPosAry )
1027 : {
1028 : GLfloat aTexCoord[8];
1029 0 : if( !UseProgram( "blendedTextureVertexShader", "blendedTextureFragmentShader" ) )
1030 0 : return;
1031 0 : mpProgram->SetTexture( "sampler", rTexture );
1032 0 : mpProgram->SetTexture( "mask", rMask );
1033 0 : mpProgram->SetTexture( "alpha", rAlpha );
1034 0 : rAlpha.GetCoord( aTexCoord, rPosAry );
1035 0 : mpProgram->SetAlphaCoord( aTexCoord );
1036 0 : mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1037 0 : DrawTextureRect( rTexture, rPosAry );
1038 0 : mpProgram->Clean();
1039 : }
1040 :
1041 0 : void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, SalColor nMaskColor, const SalTwoRect& pPosAry )
1042 : {
1043 0 : if( !UseProgram( "textureVertexShader", "maskFragmentShader" ) )
1044 0 : return;
1045 0 : mpProgram->SetColor( "color", nMaskColor, 0 );
1046 0 : mpProgram->SetTexture( "sampler", rMask );
1047 0 : mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1048 0 : DrawTextureRect( rMask, pPosAry );
1049 0 : mpProgram->Clean();
1050 : }
1051 :
1052 0 : void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect )
1053 : {
1054 0 : if( !UseProgram( "textureVertexShader", "linearGradientFragmentShader" ) )
1055 0 : return;
1056 0 : Color aStartCol = rGradient.GetStartColor();
1057 0 : Color aEndCol = rGradient.GetEndColor();
1058 0 : long nFactor = rGradient.GetStartIntensity();
1059 0 : mpProgram->SetColorWithIntensity( "start_color", aStartCol, nFactor );
1060 0 : nFactor = rGradient.GetEndIntensity();
1061 0 : mpProgram->SetColorWithIntensity( "end_color", aEndCol, nFactor );
1062 :
1063 0 : Rectangle aBoundRect;
1064 0 : Point aCenter;
1065 0 : rGradient.GetBoundRect( rRect, aBoundRect, aCenter );
1066 0 : Polygon aPoly( aBoundRect );
1067 0 : aPoly.Rotate( aCenter, rGradient.GetAngle() % 3600 );
1068 :
1069 0 : GLfloat aTexCoord[8] = { 0, 1, 1, 1, 1, 0, 0, 0 };
1070 0 : GLfloat fMin = 1.0 - 100.0 / (100.0 - rGradient.GetBorder());
1071 0 : aTexCoord[5] = aTexCoord[7] = fMin;
1072 0 : mpProgram->SetTextureCoord( aTexCoord );
1073 0 : DrawConvexPolygon( aPoly, true );
1074 : }
1075 :
1076 0 : void OpenGLSalGraphicsImpl::DrawAxialGradient( const Gradient& rGradient, const Rectangle& rRect )
1077 : {
1078 0 : if( !UseProgram( "textureVertexShader", "linearGradientFragmentShader" ) )
1079 0 : return;
1080 0 : Color aStartCol = rGradient.GetStartColor();
1081 0 : Color aEndCol = rGradient.GetEndColor();
1082 0 : long nFactor = rGradient.GetStartIntensity();
1083 0 : mpProgram->SetColorWithIntensity( "start_color", aStartCol, nFactor );
1084 0 : nFactor = rGradient.GetEndIntensity();
1085 0 : mpProgram->SetColorWithIntensity( "end_color", aEndCol, nFactor );
1086 :
1087 : /**
1088 : * Draw two rectangles with linear gradient.
1089 : *
1090 : * 1 *---* 2
1091 : * | /|
1092 : * | / | Points 0 and 3 have start color
1093 : * 0 |/__| 3 Points 1, 2, 4 and 5 have end color
1094 : * |\ |
1095 : * | \ |
1096 : * | \|
1097 : * 5 *---* 4
1098 : *
1099 : */
1100 :
1101 0 : Rectangle aRect;
1102 0 : Point aCenter;
1103 0 : rGradient.GetBoundRect( rRect, aRect, aCenter );
1104 :
1105 : // determine points 0 and 3
1106 0 : Point aPt0( aRect.Left(), (aRect.Top() + aRect.Bottom() + 1) / 2 );
1107 0 : Point aPt3( aRect.Right(), (aRect.Top() + aRect.Bottom() + 1) / 2 );
1108 :
1109 0 : Polygon aPoly( 7 );
1110 0 : aPoly.SetPoint( aPt0, 0 );
1111 0 : aPoly.SetPoint( aRect.TopLeft(), 1 );
1112 0 : aPoly.SetPoint( aRect.TopRight(), 2 );
1113 0 : aPoly.SetPoint( aPt3, 3 );
1114 0 : aPoly.SetPoint( aRect.BottomRight(), 4 );
1115 0 : aPoly.SetPoint( aRect.BottomLeft(), 5 );
1116 0 : aPoly.SetPoint( aPt0, 6 );
1117 0 : aPoly.Rotate( aCenter, rGradient.GetAngle() % 3600 );
1118 :
1119 0 : GLfloat aTexCoord[12] = { 0, 1, 1, 0, 2, 0, 3, 1, 4, 0, 5, 0 };
1120 0 : GLfloat fMin = 1.0 - 100.0 / (100.0 - rGradient.GetBorder());
1121 0 : aTexCoord[3] = aTexCoord[5] = aTexCoord[9] = aTexCoord[11] = fMin;
1122 0 : mpProgram->SetTextureCoord( aTexCoord );
1123 0 : DrawConvexPolygon( aPoly, true );
1124 : }
1125 :
1126 0 : void OpenGLSalGraphicsImpl::DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect )
1127 : {
1128 0 : if( !UseProgram( "textureVertexShader", "radialGradientFragmentShader" ) )
1129 0 : return;
1130 0 : Color aStartCol = rGradient.GetStartColor();
1131 0 : Color aEndCol = rGradient.GetEndColor();
1132 0 : long nFactor = rGradient.GetStartIntensity();
1133 0 : mpProgram->SetColorWithIntensity( "start_color", aStartCol, nFactor );
1134 0 : nFactor = rGradient.GetEndIntensity();
1135 0 : mpProgram->SetColorWithIntensity( "end_color", aEndCol, nFactor );
1136 :
1137 0 : Rectangle aRect;
1138 0 : Point aCenter;
1139 0 : rGradient.GetBoundRect( rRect, aRect, aCenter );
1140 :
1141 : // adjust coordinates so that radius has distance equals to 1.0
1142 0 : double fRadius = aRect.GetWidth() / 2.0f;
1143 0 : GLfloat fWidth = rRect.GetWidth() / fRadius;
1144 0 : GLfloat fHeight = rRect.GetHeight() / fRadius;
1145 0 : GLfloat aTexCoord[8] = { 0, 0, 0, fHeight, fWidth, fHeight, fWidth, 0 };
1146 0 : mpProgram->SetTextureCoord( aTexCoord );
1147 0 : mpProgram->SetUniform2f( "center", (aCenter.X() - rRect.Left()) / fRadius,
1148 0 : (aCenter.Y() - rRect.Top()) / fRadius );
1149 0 : DrawRect( rRect );
1150 : }
1151 :
1152 :
1153 : // draw --> LineColor and FillColor and RasterOp and ClipRegion
1154 0 : void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY )
1155 : {
1156 : SAL_INFO( "vcl.opengl", "::drawPixel" );
1157 0 : if( mnLineColor != SALCOLOR_NONE )
1158 : {
1159 0 : PreDraw();
1160 0 : if( UseSolid( mnLineColor ) )
1161 0 : DrawPoint( nX, nY );
1162 0 : PostDraw();
1163 : }
1164 0 : }
1165 :
1166 0 : void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY, SalColor nSalColor )
1167 : {
1168 : SAL_INFO( "vcl.opengl", "::drawPixel" );
1169 0 : if( nSalColor != SALCOLOR_NONE )
1170 : {
1171 0 : PreDraw();
1172 0 : if( UseSolid( nSalColor ) )
1173 0 : DrawPoint( nX, nY );
1174 0 : PostDraw();
1175 : }
1176 0 : }
1177 :
1178 0 : void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 )
1179 : {
1180 : SAL_INFO( "vcl.opengl", "::drawLine" );
1181 0 : if( mnLineColor != SALCOLOR_NONE )
1182 : {
1183 0 : PreDraw();
1184 0 : if( UseSolidAA( mnLineColor ) )
1185 0 : DrawLineAA( nX1, nY1, nX2, nY2 );
1186 0 : PostDraw();
1187 : }
1188 0 : }
1189 :
1190 0 : void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeight )
1191 : {
1192 : SAL_INFO( "vcl.opengl", "::drawRect" );
1193 0 : PreDraw();
1194 :
1195 0 : if( UseSolid( mnFillColor ) )
1196 0 : DrawRect( nX, nY, nWidth, nHeight );
1197 :
1198 0 : if( UseSolid( mnLineColor ) )
1199 : {
1200 0 : const long nX1( nX );
1201 0 : const long nY1( nY );
1202 0 : const long nX2( nX + nWidth );
1203 0 : const long nY2( nY + nHeight );
1204 : const SalPoint aPoints[] = { { nX1, nY1 }, { nX2, nY1 },
1205 0 : { nX2, nY2 }, { nX1, nY2 } };
1206 0 : DrawLines( 4, aPoints, true ); // No need for AA.
1207 : }
1208 :
1209 0 : PostDraw();
1210 0 : }
1211 :
1212 0 : void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
1213 : {
1214 : SAL_INFO( "vcl.opengl", "::drawPolyLine" );
1215 :
1216 0 : if( mnLineColor != SALCOLOR_NONE && nPoints > 1 )
1217 : {
1218 0 : PreDraw();
1219 0 : if( UseSolidAA( mnLineColor ) )
1220 0 : DrawLinesAA( nPoints, pPtAry, false );
1221 0 : PostDraw();
1222 : }
1223 0 : }
1224 :
1225 0 : void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
1226 : {
1227 : SAL_INFO( "vcl.opengl", "::drawPolygon" );
1228 0 : if( nPoints == 0 )
1229 0 : return;
1230 0 : if( nPoints == 1 )
1231 : {
1232 0 : drawPixel( pPtAry[0].mnX, pPtAry[0].mnY );
1233 0 : return;
1234 : }
1235 0 : if( nPoints == 2 )
1236 : {
1237 : drawLine( pPtAry[0].mnX, pPtAry[0].mnY,
1238 0 : pPtAry[1].mnX, pPtAry[1].mnY );
1239 0 : return;
1240 : }
1241 :
1242 0 : PreDraw();
1243 :
1244 0 : if( UseSolid( mnFillColor ) )
1245 0 : DrawPolygon( nPoints, pPtAry );
1246 :
1247 0 : if( UseSolidAA( mnLineColor ) )
1248 0 : DrawLinesAA( nPoints, pPtAry, true );
1249 :
1250 0 : PostDraw();
1251 : }
1252 :
1253 0 : void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry )
1254 : {
1255 : SAL_INFO( "vcl.opengl", "::drawPolyPolygon" );
1256 0 : if( nPoly <= 0 )
1257 0 : return;
1258 :
1259 0 : PreDraw();
1260 :
1261 0 : if( UseSolid( mnFillColor ) )
1262 : {
1263 0 : if( nPoly == 1 )
1264 0 : DrawPolygon( pPoints[ 0 ], pPtAry[ 0 ] );
1265 : else
1266 : {
1267 0 : basegfx::B2DPolyPolygon polyPolygon;
1268 0 : for( sal_uInt32 i = 0; i < nPoly; ++i )
1269 : {
1270 0 : basegfx::B2DPolygon polygon;
1271 0 : for( sal_uInt32 j = 0; j < pPoints[ i ]; ++j )
1272 0 : polygon.append( basegfx::B2DPoint( pPtAry[i][j].mnX, pPtAry[i][j].mnY ) );
1273 0 : polygon.setClosed( true );
1274 0 : polyPolygon.append( polygon );
1275 0 : }
1276 0 : DrawPolyPolygon( polyPolygon );
1277 : }
1278 : }
1279 :
1280 0 : if( mnLineColor != mnFillColor && UseSolidAA( mnLineColor ) )
1281 : {
1282 : // TODO Use glMultiDrawElements or primitive restart
1283 0 : for( sal_uInt32 i = 0; i < nPoly; i++ )
1284 0 : DrawLinesAA( pPoints[i], pPtAry[i], true );
1285 : }
1286 :
1287 0 : PostDraw();
1288 : }
1289 :
1290 0 : bool OpenGLSalGraphicsImpl::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency )
1291 : {
1292 : SAL_INFO( "vcl.opengl", "::drawPolyPolygon trans " << fTransparency );
1293 0 : if( rPolyPolygon.count() <= 0 )
1294 0 : return true;
1295 :
1296 0 : PreDraw();
1297 :
1298 0 : if( UseSolid( mnFillColor, fTransparency ) )
1299 0 : DrawPolyPolygon( rPolyPolygon );
1300 :
1301 0 : if( mnLineColor != mnFillColor && UseSolid( mnLineColor, fTransparency ))
1302 : {
1303 0 : basegfx::B2DTrapezoidVector aB2DTrapVector;
1304 0 : basegfx::tools::createLineTrapezoidFromB2DPolyPolygon( aB2DTrapVector, rPolyPolygon );
1305 0 : for( size_t i = 0; i < aB2DTrapVector.size(); ++i )
1306 0 : DrawTrapezoid( aB2DTrapVector[ i ] );
1307 : }
1308 :
1309 0 : PostDraw();
1310 :
1311 0 : return true;
1312 : }
1313 :
1314 0 : bool OpenGLSalGraphicsImpl::drawPolyLine(
1315 : const ::basegfx::B2DPolygon& rPolygon,
1316 : double fTransparency,
1317 : const ::basegfx::B2DVector& rLineWidth,
1318 : basegfx::B2DLineJoin eLineJoin,
1319 : com::sun::star::drawing::LineCap eLineCap)
1320 : {
1321 : SAL_INFO( "vcl.opengl", "::drawPolyLine trans " << fTransparency );
1322 0 : if( mnLineColor == SALCOLOR_NONE )
1323 0 : return true;
1324 :
1325 0 : const bool bIsHairline = (rLineWidth.getX() == rLineWidth.getY()) && (rLineWidth.getX() <= 1.2);
1326 :
1327 : // #i101491#
1328 0 : if( !bIsHairline && (rPolygon.count() > 1000) )
1329 : {
1330 : // the used basegfx::tools::createAreaGeometry is simply too
1331 : // expensive with very big polygons; fallback to caller (who
1332 : // should use ImplLineConverter normally)
1333 : // AW: ImplLineConverter had to be removed since it does not even
1334 : // know LineJoins, so the fallback will now prepare the line geometry
1335 : // the same way.
1336 0 : return false;
1337 : }
1338 :
1339 : // #i11575#desc5#b adjust B2D tesselation result to raster positions
1340 0 : basegfx::B2DPolygon aPolygon = rPolygon;
1341 0 : const double fHalfWidth = 0.5 * rLineWidth.getX();
1342 :
1343 : // #i122456# This is probably thought to happen to align hairlines to pixel positions, so
1344 : // it should be a 0.5 translation, not more. It will definitely go wrong with fat lines
1345 0 : aPolygon.transform( basegfx::tools::createTranslateB2DHomMatrix(0.5, 0.5) );
1346 :
1347 : // shortcut for hairline drawing to improve performance
1348 : //bool bDrawnOk = true;
1349 0 : if( bIsHairline )
1350 : {
1351 : // hairlines can be drawn in a simpler way (the linejoin and linecap styles can be ignored)
1352 0 : basegfx::B2DTrapezoidVector aB2DTrapVector;
1353 0 : basegfx::tools::createLineTrapezoidFromB2DPolygon( aB2DTrapVector, aPolygon, rLineWidth.getX() );
1354 : // draw tesselation result
1355 0 : if( aB2DTrapVector.size())
1356 : {
1357 0 : PreDraw();
1358 0 : if( UseSolid( mnLineColor, fTransparency ))
1359 : {
1360 0 : for( size_t i = 0; i < aB2DTrapVector.size(); ++i )
1361 0 : DrawTrapezoid( aB2DTrapVector[ i ] );
1362 : }
1363 0 : PostDraw();
1364 : }
1365 0 : return true;
1366 : }
1367 :
1368 : // get the area polygon for the line polygon
1369 0 : if( (rLineWidth.getX() != rLineWidth.getY())
1370 0 : && !basegfx::fTools::equalZero( rLineWidth.getY() ) )
1371 : {
1372 : // prepare for createAreaGeometry() with anisotropic linewidth
1373 0 : aPolygon.transform( basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getX() / rLineWidth.getY()));
1374 : }
1375 :
1376 : // create the area-polygon for the line
1377 0 : const basegfx::B2DPolyPolygon aAreaPolyPoly( basegfx::tools::createAreaGeometry(aPolygon, fHalfWidth, eLineJoin, eLineCap) );
1378 :
1379 0 : if( (rLineWidth.getX() != rLineWidth.getY())
1380 0 : && !basegfx::fTools::equalZero( rLineWidth.getX() ) )
1381 : {
1382 : // postprocess createAreaGeometry() for anisotropic linewidth
1383 0 : aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getY() / rLineWidth.getX()));
1384 : }
1385 :
1386 0 : PreDraw();
1387 0 : if( UseSolid( mnLineColor, fTransparency ) )
1388 : {
1389 0 : for( sal_uInt32 i = 0; i < aAreaPolyPoly.count(); i++ )
1390 : {
1391 0 : const ::basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( i ) );
1392 0 : DrawPolyPolygon( aOnePoly );
1393 0 : }
1394 : }
1395 0 : PostDraw();
1396 :
1397 0 : return true;
1398 : }
1399 :
1400 0 : bool OpenGLSalGraphicsImpl::drawPolyLineBezier(
1401 : sal_uInt32 /*nPoints*/,
1402 : const SalPoint* /*pPtAry*/,
1403 : const sal_uInt8* /*pFlgAry*/ )
1404 : {
1405 0 : return false;
1406 : }
1407 :
1408 0 : bool OpenGLSalGraphicsImpl::drawPolygonBezier(
1409 : sal_uInt32 /*nPoints*/,
1410 : const SalPoint* /*pPtAry*/,
1411 : const sal_uInt8* /*pFlgAry*/ )
1412 : {
1413 0 : return false;
1414 : }
1415 :
1416 0 : bool OpenGLSalGraphicsImpl::drawPolyPolygonBezier(
1417 : sal_uInt32 /*nPoly*/,
1418 : const sal_uInt32* /*pPoints*/,
1419 : const SalPoint* const* /*pPtAry*/,
1420 : const sal_uInt8* const* /*pFlgAry*/ )
1421 : {
1422 0 : return false;
1423 : }
1424 :
1425 : // CopyArea --> No RasterOp, but ClipRegion
1426 0 : void OpenGLSalGraphicsImpl::copyArea(
1427 : long nDestX, long nDestY,
1428 : long nSrcX, long nSrcY,
1429 : long nSrcWidth, long nSrcHeight,
1430 : sal_uInt16 /*nFlags*/ )
1431 : {
1432 : SAL_INFO( "vcl.opengl", "::copyArea " << nSrcX << "," << nSrcY << " >> " << nDestX << "," << nDestY << " (" << nSrcWidth << "," << nSrcHeight << ")" );
1433 0 : OpenGLTexture aTexture;
1434 0 : SalTwoRect aPosAry(0, 0, nSrcWidth, nSrcHeight, nDestX, nDestY, nSrcWidth, nSrcHeight);
1435 :
1436 0 : PreDraw();
1437 : // TODO offscreen case
1438 0 : aTexture = OpenGLTexture( nSrcX, GetHeight() - nSrcY - nSrcHeight,
1439 0 : nSrcWidth, nSrcHeight );
1440 0 : DrawTexture( aTexture, aPosAry );
1441 0 : PostDraw();
1442 0 : }
1443 :
1444 : // CopyBits and DrawBitmap --> RasterOp and ClipRegion
1445 : // CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics
1446 0 : void OpenGLSalGraphicsImpl::DoCopyBits( const SalTwoRect& rPosAry, OpenGLSalGraphicsImpl& rImpl )
1447 : {
1448 : SAL_INFO( "vcl.opengl", "::copyBits" );
1449 :
1450 0 : if( &rImpl == this &&
1451 0 : (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) &&
1452 0 : (rPosAry.mnSrcHeight == rPosAry.mnDestHeight))
1453 : {
1454 : // short circuit if there is nothing to do
1455 0 : if( (rPosAry.mnSrcX == rPosAry.mnDestX) &&
1456 0 : (rPosAry.mnSrcY == rPosAry.mnDestY))
1457 0 : return;
1458 : // use copyArea() if source and destination context are identical
1459 : copyArea( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY,
1460 0 : rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, 0 );
1461 0 : return;
1462 : }
1463 :
1464 0 : if( rImpl.mbOffscreen )
1465 : {
1466 0 : PreDraw();
1467 0 : DrawTexture( rImpl.maOffscreenTex, rPosAry );
1468 0 : PostDraw();
1469 0 : return;
1470 : }
1471 :
1472 : SAL_WARN( "vcl.opengl", "*** NOT IMPLEMENTED *** copyBits" );
1473 : // TODO: Copy from one FBO to the other (glBlitFramebuffer)
1474 : // ie. copying from one visible window to another visible window
1475 : }
1476 :
1477 0 : void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap )
1478 : {
1479 : // check that carefully only in the debug mode
1480 : assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
1481 :
1482 0 : const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
1483 0 : OpenGLTexture& rTexture = rBitmap.GetTexture();
1484 :
1485 : SAL_INFO( "vcl.opengl", "::drawBitmap" );
1486 0 : PreDraw();
1487 0 : DrawTexture( rTexture, rPosAry );
1488 0 : PostDraw();
1489 0 : }
1490 :
1491 0 : void OpenGLSalGraphicsImpl::drawBitmap(
1492 : const SalTwoRect& /*rPosAry*/,
1493 : const SalBitmap& /*rSalBitmap*/,
1494 : SalColor /*nTransparentColor*/ )
1495 : {
1496 : OSL_FAIL( "::DrawBitmap with transparent color not supported" );
1497 0 : }
1498 :
1499 0 : void OpenGLSalGraphicsImpl::drawBitmap(
1500 : const SalTwoRect& rPosAry,
1501 : const SalBitmap& rSalBitmap,
1502 : const SalBitmap& rMaskBitmap )
1503 : {
1504 0 : const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
1505 0 : const OpenGLSalBitmap& rMask = static_cast<const OpenGLSalBitmap&>(rMaskBitmap);
1506 0 : OpenGLTexture& rTexture( rBitmap.GetTexture() );
1507 0 : OpenGLTexture& rMaskTex( rMask.GetTexture() );
1508 :
1509 : SAL_INFO( "vcl.opengl", "::drawBitmap with MASK" );
1510 0 : PreDraw();
1511 0 : DrawTextureWithMask( rTexture, rMaskTex, rPosAry );
1512 0 : PostDraw();
1513 0 : }
1514 :
1515 0 : void OpenGLSalGraphicsImpl::drawMask(
1516 : const SalTwoRect& rPosAry,
1517 : const SalBitmap& rSalBitmap,
1518 : SalColor nMaskColor )
1519 : {
1520 0 : const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
1521 0 : OpenGLTexture& rTexture( rBitmap.GetTexture() );
1522 :
1523 : SAL_INFO( "vcl.opengl", "::drawMask" );
1524 0 : PreDraw();
1525 0 : DrawMask( rTexture, nMaskColor, rPosAry );
1526 0 : PostDraw();
1527 0 : }
1528 :
1529 0 : SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long nHeight )
1530 : {
1531 0 : OpenGLSalBitmap* pBitmap = new OpenGLSalBitmap;
1532 : SAL_INFO( "vcl.opengl", "::getBitmap " << nX << "," << nY <<
1533 : " " << nWidth << "x" << nHeight );
1534 : //TODO really needed?
1535 0 : PreDraw();
1536 0 : if( !pBitmap->Create( maOffscreenTex, nX, nY, nWidth, nHeight ) )
1537 : {
1538 0 : delete pBitmap;
1539 0 : pBitmap = NULL;
1540 : }
1541 0 : PostDraw();
1542 0 : return pBitmap;
1543 : }
1544 :
1545 0 : SalColor OpenGLSalGraphicsImpl::getPixel( long nX, long nY )
1546 : {
1547 0 : char pixel[3] = { 0, 0, 0 };
1548 :
1549 0 : PreDraw();
1550 0 : nY = GetHeight() - nY - 1;
1551 0 : glReadPixels( nX, nY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
1552 0 : PostDraw();
1553 :
1554 0 : CHECK_GL_ERROR();
1555 0 : return MAKE_SALCOLOR( pixel[0], pixel[1], pixel[2] );
1556 : }
1557 :
1558 : // invert --> ClipRegion (only Windows or VirDevs)
1559 0 : void OpenGLSalGraphicsImpl::invert(
1560 : long nX, long nY,
1561 : long nWidth, long nHeight,
1562 : SalInvert nFlags)
1563 : {
1564 : // TODO Figure out what are those:
1565 : // * SAL_INVERT_50 (50/50 pattern?)
1566 : // * SAL_INVERT_TRACKFRAME (dash-line rectangle?)
1567 :
1568 0 : PreDraw();
1569 :
1570 0 : if( nFlags & SAL_INVERT_TRACKFRAME )
1571 : {
1572 : SAL_WARN("vcl.opengl", "check where this call is coming from! NOT IMPLEMENTED YET!");
1573 : }
1574 0 : else if( nFlags & SAL_INVERT_50 )
1575 : {
1576 : SAL_WARN("vcl.opengl", "check where this call is coming from! NOT IMPLEMENTED YET!");
1577 : }
1578 : else // just invert
1579 : {
1580 0 : if( UseInvert() )
1581 0 : DrawRect( nX, nY, nWidth, nHeight );
1582 : }
1583 :
1584 0 : PostDraw();
1585 0 : }
1586 :
1587 0 : void OpenGLSalGraphicsImpl::invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags )
1588 : {
1589 0 : PreDraw();
1590 :
1591 0 : if( nFlags & SAL_INVERT_TRACKFRAME )
1592 : {
1593 : SAL_WARN("vcl.opengl", "check where this call is coming from! NOT IMPLEMENTED YET!");
1594 : }
1595 0 : else if( nFlags & SAL_INVERT_50 )
1596 : {
1597 : SAL_WARN("vcl.opengl", "check where this call is coming from! NOT IMPLEMENTED YET!");
1598 : }
1599 : else // just invert
1600 : {
1601 0 : if( UseInvert() )
1602 0 : DrawPolygon( nPoints, pPtAry );
1603 : }
1604 :
1605 0 : PostDraw();
1606 0 : }
1607 :
1608 0 : bool OpenGLSalGraphicsImpl::drawEPS(
1609 : long /*nX*/, long /*nY*/,
1610 : long /*nWidth*/, long /*nHeight*/,
1611 : void* /*pPtr*/,
1612 : sal_uLong /*nSize*/ )
1613 : {
1614 0 : return false;
1615 : }
1616 :
1617 0 : bool OpenGLSalGraphicsImpl::blendBitmap(
1618 : const SalTwoRect& rPosAry,
1619 : const SalBitmap& rSalBitmap )
1620 : {
1621 0 : const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
1622 0 : OpenGLTexture& rTexture( rBitmap.GetTexture() );
1623 :
1624 : SAL_INFO( "vcl.opengl", "::blendBitmap" );
1625 0 : PreDraw();
1626 0 : glEnable( GL_BLEND );
1627 0 : glBlendFunc( GL_ZERO, GL_SRC_COLOR );
1628 0 : DrawTexture( rTexture, rPosAry );
1629 0 : glDisable( GL_BLEND );
1630 0 : PostDraw();
1631 0 : return true;
1632 : }
1633 :
1634 0 : bool OpenGLSalGraphicsImpl::blendAlphaBitmap(
1635 : const SalTwoRect& rPosAry,
1636 : const SalBitmap& rSalSrcBitmap,
1637 : const SalBitmap& rSalMaskBitmap,
1638 : const SalBitmap& rSalAlphaBitmap )
1639 : {
1640 0 : const OpenGLSalBitmap& rSrcBitmap = static_cast<const OpenGLSalBitmap&>(rSalSrcBitmap);
1641 0 : const OpenGLSalBitmap& rMaskBitmap = static_cast<const OpenGLSalBitmap&>(rSalMaskBitmap);
1642 0 : const OpenGLSalBitmap& rAlphaBitmap = static_cast<const OpenGLSalBitmap&>(rSalAlphaBitmap);
1643 0 : OpenGLTexture& rTexture( rSrcBitmap.GetTexture() );
1644 0 : OpenGLTexture& rMask( rMaskBitmap.GetTexture() );
1645 0 : OpenGLTexture& rAlpha( rAlphaBitmap.GetTexture() );
1646 :
1647 : SAL_INFO( "vcl.opengl", "::blendAlphaBitmap" );
1648 0 : PreDraw();
1649 0 : DrawBlendedTexture( rTexture, rMask, rAlpha, rPosAry );
1650 0 : PostDraw();
1651 0 : return true;
1652 : }
1653 :
1654 : /** Render bitmap with alpha channel
1655 :
1656 : @param rSourceBitmap
1657 : Source bitmap to blit
1658 :
1659 : @param rAlphaBitmap
1660 : Alpha channel to use for blitting
1661 :
1662 : @return true, if the operation succeeded, and false
1663 : otherwise. In this case, clients should try to emulate alpha
1664 : compositing themselves
1665 : */
1666 0 : bool OpenGLSalGraphicsImpl::drawAlphaBitmap(
1667 : const SalTwoRect& rPosAry,
1668 : const SalBitmap& rSalBitmap,
1669 : const SalBitmap& rAlphaBitmap )
1670 : {
1671 0 : const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
1672 0 : const OpenGLSalBitmap& rAlpha = static_cast<const OpenGLSalBitmap&>(rAlphaBitmap);
1673 0 : OpenGLTexture& rTexture( rBitmap.GetTexture() );
1674 0 : OpenGLTexture& rAlphaTex( rAlpha.GetTexture() );
1675 :
1676 : SAL_INFO( "vcl.opengl", "::drawAlphaBitmap" );
1677 0 : PreDraw();
1678 0 : DrawTextureWithMask( rTexture, rAlphaTex, rPosAry );
1679 0 : PostDraw();
1680 0 : return true;
1681 : }
1682 :
1683 : /** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system */
1684 0 : bool OpenGLSalGraphicsImpl::drawTransformedBitmap(
1685 : const basegfx::B2DPoint& rNull,
1686 : const basegfx::B2DPoint& rX,
1687 : const basegfx::B2DPoint& rY,
1688 : const SalBitmap& rSrcBitmap,
1689 : const SalBitmap* pAlphaBitmap)
1690 : {
1691 0 : const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSrcBitmap);
1692 0 : const OpenGLSalBitmap* pMaskBitmap = static_cast<const OpenGLSalBitmap*>(pAlphaBitmap);
1693 0 : OpenGLTexture& rTexture( rBitmap.GetTexture() );
1694 0 : OpenGLTexture aMask; // no texture
1695 :
1696 0 : if( pMaskBitmap != NULL )
1697 0 : aMask = pMaskBitmap->GetTexture();
1698 :
1699 : SAL_INFO( "vcl.opengl", "::drawTransformedBitmap" );
1700 0 : PreDraw();
1701 0 : DrawTransformedTexture( rTexture, aMask, rNull, rX, rY );
1702 0 : PostDraw();
1703 :
1704 0 : return true;
1705 : }
1706 :
1707 : /** Render solid rectangle with given transparency
1708 :
1709 : @param nTransparency
1710 : Transparency value (0-255) to use. 0 blits and opaque, 255 a
1711 : fully transparent rectangle
1712 : */
1713 0 : bool OpenGLSalGraphicsImpl::drawAlphaRect(
1714 : long nX, long nY,
1715 : long nWidth, long nHeight,
1716 : sal_uInt8 nTransparency )
1717 : {
1718 : SAL_INFO( "vcl.opengl", "::drawAlphaRect" );
1719 0 : if( mnFillColor != SALCOLOR_NONE && nTransparency < 100 )
1720 : {
1721 0 : PreDraw();
1722 0 : UseSolid( mnFillColor, nTransparency );
1723 0 : DrawRect( nX, nY, nWidth, nHeight );
1724 0 : PostDraw();
1725 : }
1726 :
1727 0 : return true;
1728 : }
1729 :
1730 0 : bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
1731 : const Gradient& rGradient)
1732 : {
1733 0 : Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
1734 :
1735 : SAL_INFO( "vcl.opengl", "::drawGradient" );
1736 :
1737 0 : if( aBoundRect.IsEmpty() )
1738 0 : return true;
1739 :
1740 0 : if( rGradient.GetStyle() != GradientStyle_LINEAR &&
1741 0 : rGradient.GetStyle() != GradientStyle_AXIAL &&
1742 0 : rGradient.GetStyle() != GradientStyle_RADIAL )
1743 0 : return false;
1744 :
1745 0 : aBoundRect.Left()--;
1746 0 : aBoundRect.Top()--;
1747 0 : aBoundRect.Right()++;
1748 0 : aBoundRect.Bottom()++;
1749 :
1750 0 : PreDraw();
1751 :
1752 : #define FIXME_BROKEN_STENCIL_FOR_GRADIENTS 0
1753 : #if FIXME_BROKEN_STENCIL_FOR_GRADIENTS
1754 : ImplSetClipBit( vcl::Region( rPolyPoly ), 0x02 );
1755 : if( mbUseStencil )
1756 : {
1757 : glEnable( GL_STENCIL_TEST );
1758 : glStencilFunc( GL_EQUAL, 3, 0xFF );
1759 : }
1760 : else
1761 : {
1762 : glEnable( GL_STENCIL_TEST );
1763 : glStencilFunc( GL_EQUAL, 2, 0xFF );
1764 : }
1765 : #endif
1766 :
1767 : // if border >= 100%, draw solid rectangle with start color
1768 0 : if( rGradient.GetBorder() >= 100.0 )
1769 : {
1770 0 : Color aCol = rGradient.GetStartColor();
1771 0 : long nF = rGradient.GetStartIntensity();
1772 0 : if( UseSolid( MAKE_SALCOLOR( aCol.GetRed() * nF / 100,
1773 : aCol.GetGreen() * nF / 100,
1774 0 : aCol.GetBlue() * nF / 100 ) ) )
1775 0 : DrawRect( aBoundRect );
1776 : }
1777 0 : else if( rGradient.GetStyle() == GradientStyle_LINEAR )
1778 : {
1779 0 : DrawLinearGradient( rGradient, aBoundRect );
1780 : }
1781 0 : else if( rGradient.GetStyle() == GradientStyle_AXIAL )
1782 : {
1783 0 : DrawAxialGradient( rGradient, aBoundRect );
1784 : }
1785 0 : else if( rGradient.GetStyle() == GradientStyle_RADIAL )
1786 : {
1787 0 : DrawRadialGradient( rGradient, aBoundRect );
1788 : }
1789 :
1790 : #if FIXME_BROKEN_STENCIL_FOR_GRADIENTS
1791 : if( !mbUseStencil )
1792 : glDisable( GL_STENCIL_TEST );
1793 : #endif
1794 0 : PostDraw();
1795 :
1796 0 : CHECK_GL_ERROR();
1797 0 : return true;
1798 : }
1799 :
1800 0 : void OpenGLSalGraphicsImpl::beginPaint()
1801 : {
1802 0 : if( !AcquireContext() )
1803 0 : return;
1804 :
1805 0 : mpContext->mnPainting++;
1806 : }
1807 :
1808 0 : void OpenGLSalGraphicsImpl::endPaint()
1809 : {
1810 0 : if( !AcquireContext() )
1811 0 : return;
1812 :
1813 0 : mpContext->mnPainting--;
1814 : assert( mpContext->mnPainting >= 0 );
1815 0 : if( mpContext->mnPainting == 0 && !mbOffscreen )
1816 : {
1817 0 : mpContext->makeCurrent();
1818 0 : mpContext->AcquireDefaultFramebuffer();
1819 0 : glFlush();
1820 : }
1821 :
1822 0 : CHECK_GL_ERROR();
1823 801 : }
1824 :
1825 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|