]> git.mxchange.org Git - simgear.git/blob - simgear/canvas/ShivaVG/src/shContext.c
Update for OpenSceneGraph 3.3.2 API changes.
[simgear.git] / simgear / canvas / ShivaVG / src / shContext.c
1 /*
2  * Copyright (c) 2007 Ivan Leben
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  * 
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  * 
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library in the file COPYING;
16  * if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  */
20
21 #include <vg/openvg.h>
22 #include "shContext.h"
23 #include <string.h>
24 #include <stdio.h>
25
26 /*-----------------------------------------------------
27  * Simple functions to create a VG context instance
28  * on top of an existing OpenGL context.
29  * TODO: There is no mechanics yet to asure the OpenGL
30  * context exists and to choose which context / window
31  * to bind to. 
32  *-----------------------------------------------------*/
33
34 static VGContext *g_context = NULL;
35
36 VG_API_CALL VGboolean vgCreateContextSH(VGint width, VGint height)
37 {
38   /* return if already created */
39   if (g_context) return VG_TRUE;
40   
41   /* create new context */
42   SH_NEWOBJ(VGContext, g_context);
43   if (!g_context) return VG_FALSE;
44   
45   /* init surface info */
46   g_context->surfaceWidth = width;
47   g_context->surfaceHeight = height;
48   
49   /* setup GL projection */
50   /* We handle viewport and projection ourselves...
51
52   glViewport(0,0,width,height);
53   
54   glMatrixMode(GL_PROJECTION);
55   glLoadIdentity();
56   glOrtho(0, width, 0, height, -1, 1);
57   
58   glMatrixMode(GL_MODELVIEW);
59   glLoadIdentity();*/
60   
61   return VG_TRUE;
62 }
63
64 VG_API_CALL VGboolean vgHasContextSH()
65 {
66   return g_context != NULL;
67 }
68
69 VG_API_CALL void vgResizeSurfaceSH(VGint width, VGint height)
70 {
71   VG_GETCONTEXT(VG_NO_RETVAL);
72   
73   /* update surface info */
74   context->surfaceWidth = width;
75   context->surfaceHeight = height;
76   
77   /* setup GL projection */
78   glViewport(0,0,width,height);
79   
80   glMatrixMode(GL_PROJECTION);
81   glLoadIdentity();
82   glOrtho(0, width, 0, height, -1, 1);
83   
84   glMatrixMode(GL_MODELVIEW);
85   glLoadIdentity();
86   
87   VG_RETURN(VG_NO_RETVAL);
88 }
89
90 VG_API_CALL void vgDestroyContextSH()
91 {
92   /* return if already released */
93   if (!g_context) return;
94   
95   /* delete context object */
96   SH_DELETEOBJ(VGContext, g_context);
97   g_context = NULL;
98 }
99
100 VGContext* shGetContext()
101 {
102   SH_ASSERT(g_context);
103   return g_context;
104 }
105
106 /*-----------------------------------------------------
107  * VGContext constructor
108  *-----------------------------------------------------*/
109
110 void shLoadExtensions(VGContext *c);
111
112 void VGContext_ctor(VGContext *c)
113 {
114   /* Surface info */
115   c->surfaceWidth = 0;
116   c->surfaceHeight = 0;
117   
118   /* GetString info */
119   strncpy(c->vendor, "Ivan Leben", sizeof(c->vendor));
120   strncpy(c->renderer, "ShivaVG 0.1.0", sizeof(c->renderer));
121   strncpy(c->version, "1.0", sizeof(c->version));
122   strncpy(c->extensions, "", sizeof(c->extensions));
123   
124   /* Mode settings */
125   c->matrixMode = VG_MATRIX_PATH_USER_TO_SURFACE;
126   c->fillRule = VG_EVEN_ODD;
127   c->imageQuality = VG_IMAGE_QUALITY_FASTER;
128   c->renderingQuality = VG_RENDERING_QUALITY_BETTER;
129   c->blendMode = VG_BLEND_SRC_OVER;
130   c->imageMode = VG_DRAW_IMAGE_NORMAL;
131   
132   /* Scissor rectangles */
133   SH_INITOBJ(SHRectArray, c->scissor);
134   c->scissoring = VG_FALSE;
135   c->masking = VG_FALSE;
136   
137   /* Stroke parameters */
138   c->strokeLineWidth = 1.0f;
139   c->strokeCapStyle = VG_CAP_BUTT;
140   c->strokeJoinStyle = VG_JOIN_MITER;
141   c->strokeMiterLimit = 4.0f;
142   c->strokeDashPhase = 0.0f;
143   c->strokeDashPhaseReset = VG_FALSE;
144   SH_INITOBJ(SHFloatArray, c->strokeDashPattern);
145   
146   /* Edge fill color for vgConvolve and pattern paint */
147   CSET(c->tileFillColor, 0,0,0,0);
148   
149   /* Color for vgClear */
150   CSET(c->clearColor, 0,0,0,0);
151   
152   /* Color components layout inside pixel */
153   c->pixelLayout = VG_PIXEL_LAYOUT_UNKNOWN;
154   
155   /* Source format for image filters */
156   c->filterFormatLinear = VG_FALSE;
157   c->filterFormatPremultiplied = VG_FALSE;
158   c->filterChannelMask = VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA;
159   
160   /* Matrices */
161   SH_INITOBJ(SHMatrix3x3, c->pathTransform);
162   SH_INITOBJ(SHMatrix3x3, c->imageTransform);
163   SH_INITOBJ(SHMatrix3x3, c->fillTransform);
164   SH_INITOBJ(SHMatrix3x3, c->strokeTransform);
165   
166   /* Paints */
167   c->fillPaint = NULL;
168   c->strokePaint = NULL;
169   SH_INITOBJ(SHPaint, c->defaultPaint);
170   
171   /* Error */
172   c->error = VG_NO_ERROR;
173   
174   /* Resources */
175   SH_INITOBJ(SHPathArray, c->paths);
176   SH_INITOBJ(SHPaintArray, c->paints);
177   SH_INITOBJ(SHImageArray, c->images);
178
179   shLoadExtensions(c);
180 }
181
182 /*-----------------------------------------------------
183  * VGContext constructor
184  *-----------------------------------------------------*/
185
186 void VGContext_dtor(VGContext *c)
187 {
188   int i;
189   
190   SH_DEINITOBJ(SHRectArray, c->scissor);
191   SH_DEINITOBJ(SHFloatArray, c->strokeDashPattern);
192   
193   /* Destroy resources */
194   for (i=0; i<c->paths.size; ++i)
195     SH_DELETEOBJ(SHPath, c->paths.items[i]);
196   
197   for (i=0; i<c->paints.size; ++i)
198     SH_DELETEOBJ(SHPaint, c->paints.items[i]);
199   
200   for (i=0; i<c->images.size; ++i)
201     SH_DELETEOBJ(SHImage, c->images.items[i]);
202 }
203
204 /*--------------------------------------------------
205  * Tries to find resources in this context
206  *--------------------------------------------------*/
207
208 SHint shIsValidPath(VGContext *c, VGHandle h)
209 {
210   int index = shPathArrayFind(&c->paths, (SHPath*)h);
211   return (index == -1) ? 0 : 1;
212 }
213
214 SHint shIsValidPaint(VGContext *c, VGHandle h)
215 {
216   int index = shPaintArrayFind(&c->paints, (SHPaint*)h);
217   return (index == -1) ? 0 : 1;
218 }
219
220 SHint shIsValidImage(VGContext *c, VGHandle h)
221 {
222   int index = shImageArrayFind(&c->images, (SHImage*)h);
223   return (index == -1) ? 0 : 1;
224 }
225
226 /*--------------------------------------------------
227  * Tries to find a resources in this context and
228  * return its type or invalid flag.
229  *--------------------------------------------------*/
230
231 SHResourceType shGetResourceType(VGContext *c, VGHandle h)
232 {
233   if (shIsValidPath(c, h))
234     return SH_RESOURCE_PATH;
235   
236   else if (shIsValidPaint(c, h))
237     return SH_RESOURCE_PAINT;
238   
239   else if (shIsValidImage(c, h))
240     return SH_RESOURCE_IMAGE;
241   
242   else
243     return SH_RESOURCE_INVALID;
244 }
245
246 /*-----------------------------------------------------
247  * Sets the specified error on the given context if
248  * there is no pending error yet
249  *-----------------------------------------------------*/
250
251 void shSetError(VGContext *c, VGErrorCode e)
252 {
253   if (c->error == VG_NO_ERROR)
254     c->error = e;
255 }
256
257 /*--------------------------------------------------
258  * Returns the oldest error pending on the current
259  * context and clears its error code
260  *--------------------------------------------------*/
261
262 VG_API_CALL VGErrorCode vgGetError(void)
263 {
264   VGErrorCode error;
265   VG_GETCONTEXT(VG_NO_CONTEXT_ERROR);
266   error = context->error;
267   context->error = VG_NO_ERROR;
268   VG_RETURN(error);
269 }
270
271 VG_API_CALL void vgFlush(void)
272 {
273   VG_GETCONTEXT(VG_NO_RETVAL);
274   glFlush();
275   VG_RETURN(VG_NO_RETVAL);
276 }
277
278 VG_API_CALL void vgFinish(void)
279 {
280   VG_GETCONTEXT(VG_NO_RETVAL);
281   glFinish();
282   VG_RETURN(VG_NO_RETVAL);
283 }
284
285 VG_API_CALL void vgMask(VGImage mask, VGMaskOperation operation,
286                         VGint x, VGint y, VGint width, VGint height)
287 {
288 }
289
290 VG_API_CALL void vgClear(VGint x, VGint y, VGint width, VGint height)
291 {
292   VG_GETCONTEXT(VG_NO_RETVAL);
293   
294   /* Clip to window */
295   if (x < 0) x = 0;
296   if (y < 0) y = 0;
297   if (width > context->surfaceWidth) width = context->surfaceWidth;
298   if (height > context->surfaceHeight) height = context->surfaceHeight;
299   
300   /* Check if scissoring needed */
301   if (x > 0 || y > 0 ||
302       width < context->surfaceWidth ||
303       height < context->surfaceHeight) {
304     
305     glScissor(x, y, width, height);
306     glEnable(GL_SCISSOR_TEST);
307   }
308   
309   /* Clear GL color buffer */
310   /* TODO: what about stencil and depth? when do we clear that?
311      we would need some kind of special "begin" function at
312      beginning of each drawing or clear the planes prior to each
313      drawing where it takes places */
314   glClearColor(context->clearColor.r,
315                context->clearColor.g,
316                context->clearColor.b,
317                context->clearColor.a);
318   
319   glClear(GL_COLOR_BUFFER_BIT |
320           GL_STENCIL_BUFFER_BIT |
321           GL_DEPTH_BUFFER_BIT);
322   
323   glDisable(GL_SCISSOR_TEST);
324   
325   VG_RETURN(VG_NO_RETVAL);
326 }
327
328 /*-----------------------------------------------------------
329  * Returns the matrix currently selected via VG_MATRIX_MODE
330  *-----------------------------------------------------------*/
331
332 SHMatrix3x3* shCurrentMatrix(VGContext *c)
333 {
334   switch(c->matrixMode) {
335   case VG_MATRIX_PATH_USER_TO_SURFACE:
336     return &c->pathTransform;
337   case VG_MATRIX_IMAGE_USER_TO_SURFACE:
338     return &c->imageTransform;
339   case VG_MATRIX_FILL_PAINT_TO_USER:
340     return &c->fillTransform;
341   default:
342     return &c->strokeTransform;
343   }
344 }
345
346 /*--------------------------------------
347  * Sets the current matrix to identity
348  *--------------------------------------*/
349
350 VG_API_CALL void vgLoadIdentity(void)
351 {
352   SHMatrix3x3 *m;
353   VG_GETCONTEXT(VG_NO_RETVAL);
354   
355   m = shCurrentMatrix(context);
356   IDMAT((*m));
357   
358   VG_RETURN(VG_NO_RETVAL);
359 }
360
361 /*-------------------------------------------------------------
362  * Loads values into the current matrix from the given array.
363  * Matrix affinity is preserved if an affine matrix is loaded.
364  *-------------------------------------------------------------*/
365
366 VG_API_CALL void vgLoadMatrix(const VGfloat * mm)
367 {
368   SHMatrix3x3 *m;
369   VG_GETCONTEXT(VG_NO_RETVAL);
370   
371   VG_RETURN_ERR_IF(!mm, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
372   /* TODO: check matrix array alignment */
373   
374   m = shCurrentMatrix(context);
375
376   if (context->matrixMode == VG_MATRIX_IMAGE_USER_TO_SURFACE) {
377     
378     SETMAT((*m),
379            mm[0], mm[3], mm[6],
380            mm[1], mm[4], mm[7],
381            mm[2], mm[5], mm[8]);
382   }else{
383     
384     SETMAT((*m),
385            mm[0], mm[3], mm[6],
386            mm[1], mm[4], mm[7],
387            0.0f,  0.0f,  1.0f);
388   }
389   
390   VG_RETURN(VG_NO_RETVAL);
391 }
392
393 /*---------------------------------------------------------------
394  * Outputs the values of the current matrix into the given array
395  *---------------------------------------------------------------*/
396
397 VG_API_CALL void vgGetMatrix(VGfloat * mm)
398 {
399   SHMatrix3x3 *m; int i,j,k=0;
400   VG_GETCONTEXT(VG_NO_RETVAL);
401   
402   VG_RETURN_ERR_IF(!mm, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
403   /* TODO: check matrix array alignment */
404   
405   m = shCurrentMatrix(context);
406   
407   for (i=0; i<3; ++i)
408     for (j=0; j<3; ++j)
409       mm[k++] = m->m[j][i];
410   
411   VG_RETURN(VG_NO_RETVAL);
412 }
413
414 /*-------------------------------------------------------------
415  * Right-multiplies the current matrix with the one specified
416  * in the given array. Matrix affinity is preserved if an
417  * affine matrix is begin multiplied.
418  *-------------------------------------------------------------*/
419
420 VG_API_CALL void vgMultMatrix(const VGfloat * mm)
421 {
422   SHMatrix3x3 *m, mul, temp;
423   VG_GETCONTEXT(VG_NO_RETVAL);
424   
425   VG_RETURN_ERR_IF(!mm, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
426   /* TODO: check matrix array alignment */
427   
428   m = shCurrentMatrix(context);
429   
430   if (context->matrixMode == VG_MATRIX_IMAGE_USER_TO_SURFACE) {
431     
432     SETMAT(mul,
433            mm[0], mm[3], mm[6],
434            mm[1], mm[4], mm[7],
435            mm[2], mm[5], mm[8]);
436   }else{
437     
438     SETMAT(mul,
439            mm[0], mm[3], mm[6],
440            mm[1], mm[4], mm[7],
441            0.0f,  0.0f,  1.0f);
442   }
443   
444   MULMATMAT((*m), mul, temp);
445   SETMATMAT((*m), temp);
446   
447   VG_RETURN(VG_NO_RETVAL);
448 }
449
450 VG_API_CALL void vgTranslate(VGfloat tx, VGfloat ty)
451 {
452   SHMatrix3x3 *m;
453   VG_GETCONTEXT(VG_NO_RETVAL);
454   
455   m = shCurrentMatrix(context);
456   TRANSLATEMATR((*m), tx, ty);
457   
458   VG_RETURN(VG_NO_RETVAL);
459 }
460
461 VG_API_CALL void vgScale(VGfloat sx, VGfloat sy)
462 {
463   SHMatrix3x3 *m;
464   VG_GETCONTEXT(VG_NO_RETVAL);
465   
466   m = shCurrentMatrix(context);
467   SCALEMATR((*m), sx, sy);
468   
469   VG_RETURN(VG_NO_RETVAL);
470 }
471
472 VG_API_CALL void vgShear(VGfloat shx, VGfloat shy)
473 {
474   SHMatrix3x3 *m;
475   VG_GETCONTEXT(VG_NO_RETVAL);
476   
477   m = shCurrentMatrix(context);
478   SHEARMATR((*m), shx, shy);
479   
480   VG_RETURN(VG_NO_RETVAL);
481 }
482
483 VG_API_CALL void vgRotate(VGfloat angle)
484 {
485   SHfloat a;
486   SHMatrix3x3 *m;
487   VG_GETCONTEXT(VG_NO_RETVAL);
488   
489   a = SH_DEG2RAD(angle);
490   m = shCurrentMatrix(context);
491   ROTATEMATR((*m), a);
492   
493   VG_RETURN(VG_NO_RETVAL);
494 }
495
496 VG_API_CALL VGHardwareQueryResult vgHardwareQuery(VGHardwareQueryType key,
497                                                   VGint setting)
498 {
499   return VG_HARDWARE_UNACCELERATED;
500 }