]> git.mxchange.org Git - simgear.git/blob - simgear/canvas/ShivaVG/src/shImage.c
Update for OpenSceneGraph 3.3.2 API changes.
[simgear.git] / simgear / canvas / ShivaVG / src / shImage.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 "shImage.h"
23 #include "shContext.h"
24 #include <string.h>
25 #include <stdio.h>
26
27 #define _ITEM_T SHColor
28 #define _ARRAY_T SHColorArray
29 #define _FUNC_T shColorArray
30 #define _ARRAY_DEFINE
31 #define _COMPARE_T(c1,c2) 0
32 #include "shArrayBase.h"
33
34 #define _ITEM_T SHImage*
35 #define _ARRAY_T SHImageArray
36 #define _FUNC_T shImageArray
37 #define _ARRAY_DEFINE
38 #include "shArrayBase.h"
39
40 #ifndef SH_NO_IMAGE
41
42 /*-----------------------------------------------------------
43  * Prepares the proper pixel pack/unpack info for the given
44  * OpenVG image format.
45  *-----------------------------------------------------------*/
46
47 void shSetupImageFormat(VGImageFormat vg, SHImageFormatDesc *f)
48 {
49   SHuint8 abits = 0;
50   SHuint8 tshift = 0;
51   SHuint8 tmask = 0;
52   SHuint32 amsbBit = 0;
53   SHuint32 bgrBit = 0;
54
55   /* Store VG format name */
56   f->vgformat = vg;
57
58   /* Check if alpha on MSB or colors in BGR order */
59   amsbBit = ((vg & (1 << 6)) >> 6);
60   bgrBit = ((vg & (1 << 7)) >> 7);
61
62   /* Find component ordering and size */
63   switch(vg & 0x1F)
64   {
65   case 0: /* VG_sRGBX_8888 */
66   case 7: /* VG_lRGBX_8888 */
67     f->bytes = 4;
68     f->rmask = 0xFF000000;
69     f->rshift = 24;
70     f->rmax = 255;
71     f->gmask = 0x00FF0000;
72     f->gshift = 16;
73     f->gmax = 255;
74     f->bmask = 0x0000FF00;
75     f->bshift = 8;
76     f->bmax = 255;
77     f->amask = 0x0;
78     f->ashift = 0;
79     f->amax = 1;
80     break;
81   case 1: /* VG_sRGBA_8888 */
82   case 2: /* VG_sRGBA_8888_PRE */
83   case 8: /* VG_lRGBA_8888 */
84   case 9: /* VG_lRGBA_8888_PRE */
85     f->bytes = 4;
86     f->rmask = 0xFF000000;
87     f->rshift = 24;
88     f->rmax = 255;
89     f->gmask = 0x00FF0000;
90     f->gshift = 16;
91     f->gmax = 255;
92     f->bmask = 0x0000FF00;
93     f->bshift = 8;
94     f->bmax = 255;
95     f->amask = 0x000000FF;
96     f->ashift = 0;
97     f->amax = 255;
98     break;
99   case 3: /* VG_sRGB_565 */
100     f->bytes = 2;
101     f->rmask = 0xF800;
102     f->rshift = 11;
103     f->rmax = 31;
104     f->gmask = 0x07E0;
105     f->gshift = 5;
106     f->gmax = 63;
107     f->bmask = 0x001F;
108     f->bshift = 0;
109     f->bmax = 31;
110     f->amask = 0x0;
111     f->ashift = 0;
112     f->amax = 1;
113     break;
114   case 4: /* VG_sRGBA_5551 */
115     f->bytes = 2;
116     f->rmask = 0xF800;
117     f->rshift = 11;
118     f->rmax = 31;
119     f->gmask = 0x07C0;
120     f->gshift = 6;
121     f->gmax = 31;
122     f->bmask = 0x003E;
123     f->bshift = 1;
124     f->bmax = 31;
125     f->amask = 0x0001;
126     f->ashift = 0;
127     f->amax = 1;
128     break;
129   case 5: /* VG_sRGBA_4444 */
130     f->bytes = 2;
131     f->rmask = 0xF000;
132     f->rshift = 12;
133     f->rmax = 15;
134     f->gmask = 0x0F00;
135     f->gshift = 8;
136     f->gmax = 15;
137     f->bmask = 0x00F0;
138     f->bshift = 4;
139     f->bmax = 15;
140     f->amask = 0x000F;
141     f->ashift = 0;
142     f->amax = 15;
143     break;
144   case 6: /* VG_sL_8 */
145   case 10: /* VG_lL_8 */
146     f->bytes = 1;
147     f->rmask = 0xFF;
148     f->rshift = 0;
149     f->rmax = 255;
150     f->gmask = 0xFF;
151     f->gshift = 0;
152     f->gmax = 255;
153     f->bmask = 0xFF;
154     f->bshift = 0;
155     f->bmax = 255;
156     f->amask = 0x0;
157     f->ashift = 0;
158     f->amax = 1;
159     break;
160   case 11: /* VG_A_8 */
161     f->bytes = 1;
162     f->rmask = 0x0;
163     f->rshift = 0;
164     f->rmax = 1;
165     f->gmask = 0x0;
166     f->gshift = 0;
167     f->gmax = 1;
168     f->bmask = 0x0;
169     f->bshift = 0;
170     f->bmax = 1;
171     f->amask = 0xFF;
172     f->ashift = 0;
173     f->amax = 255;
174     break;
175   case 12: /* VG_BW_1 */
176     f->bytes = 1;
177     f->rmask = 0x0;
178     f->rshift = 0;
179     f->rmax = 1;
180     f->gmask = 0x0;
181     f->gshift = 0;
182     f->gmax = 1;
183     f->bmask = 0x0;
184     f->bshift = 0;
185     f->bmax = 1;
186     f->amask = 0x0;
187     f->ashift = 0;
188     f->amax = 1;
189     break;
190   }
191
192   /* Check for A,X at MSB */
193   if (amsbBit) {
194
195     abits = f->bshift;
196
197     f->rshift -= abits;
198     f->gshift -= abits;
199     f->bshift -= abits;
200     f->ashift = f->bytes * 8 - abits;
201
202     f->rmask >>= abits;
203     f->gmask >>= abits;
204     f->bmask >>= abits;
205     f->amask <<= f->bytes * 8 - abits;
206   }
207
208   /* Check for BGR ordering */
209   if (bgrBit) {
210
211     tshift = f->bshift;
212     f->bshift = f->rshift;
213     f->rshift = tshift;
214
215     tmask = f->bmask;
216     f->bmask = f->rmask;
217     f->rmask = tmask;
218   }
219
220   /* Find proper mapping to OpenGL formats */
221   switch(vg & 0x1F)
222   {
223   case VG_sRGBX_8888:
224   case VG_lRGBX_8888:
225   case VG_sRGBA_8888:
226   case VG_sRGBA_8888_PRE:
227   case VG_lRGBA_8888:
228   case VG_lRGBA_8888_PRE:
229
230     f->glintformat = GL_RGBA;
231
232     if (amsbBit == 0 && bgrBit == 0) {
233       f->glformat = GL_RGBA;
234       f->gltype = GL_UNSIGNED_INT_8_8_8_8;
235
236     }else if (amsbBit == 1 && bgrBit == 0) {
237       f->glformat = GL_BGRA;
238       f->gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
239
240     }else if (amsbBit == 0 && bgrBit == 1) {
241       f->glformat = GL_BGRA;
242       f->gltype = GL_UNSIGNED_INT_8_8_8_8;
243
244     }else if (amsbBit == 1 && bgrBit == 1) {
245       f->glformat = GL_RGBA;
246       f->gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
247     }
248
249     break;
250   case VG_sRGBA_5551:
251
252     f->glintformat = GL_RGBA;
253
254     if (amsbBit == 0 && bgrBit == 0) {
255       f->glformat = GL_RGBA;
256       f->gltype = GL_UNSIGNED_SHORT_5_5_5_1;
257
258     }else if (amsbBit == 1 && bgrBit == 0) {
259       f->glformat = GL_BGRA;
260       f->gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
261
262     }else if (amsbBit == 0 && bgrBit == 1) {
263       f->glformat = GL_BGRA;
264       f->gltype = GL_UNSIGNED_SHORT_5_5_5_1;
265
266     }else if (amsbBit == 1 && bgrBit == 1) {
267       f->glformat = GL_RGBA;
268       f->gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
269     }
270
271     break;
272   case VG_sRGBA_4444:
273
274     f->glintformat = GL_RGBA;
275
276     if (amsbBit == 0 && bgrBit == 0) {
277       f->glformat = GL_RGBA;
278       f->gltype = GL_UNSIGNED_SHORT_4_4_4_4;
279
280     }else if (amsbBit == 1 && bgrBit == 0) {
281       f->glformat = GL_BGRA;
282       f->gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV;
283
284     }else if (amsbBit == 0 && bgrBit == 1) {
285       f->glformat = GL_BGRA;
286       f->gltype = GL_UNSIGNED_SHORT_4_4_4_4;
287
288     }else if (amsbBit == 1 && bgrBit == 1) {
289       f->glformat = GL_RGBA;
290       f->gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV;
291     }
292
293     break;
294   case VG_sRGB_565:
295
296     f->glintformat = GL_RGB;
297
298     if (bgrBit == 0) {
299       f->glformat = GL_RGB;
300       f->gltype = GL_UNSIGNED_SHORT_5_6_5;
301
302     }else if (bgrBit == 1) {
303       f->glformat = GL_RGB;
304       f->gltype = GL_UNSIGNED_SHORT_5_6_5;
305     }
306
307     break;
308   case VG_sL_8:
309   case VG_lL_8:
310
311     f->glintformat = GL_LUMINANCE;
312     f->glformat = GL_LUMINANCE;
313     f->gltype = GL_UNSIGNED_BYTE;
314
315     break;
316   case VG_A_8:
317
318     f->glintformat = GL_ALPHA;
319     f->glformat = GL_ALPHA;
320     f->gltype = GL_UNSIGNED_BYTE;
321
322     break;
323   case VG_BW_1:
324
325     f->glintformat = 0;
326     f->glformat = 0;
327     f->gltype = 0;
328     break;
329   }
330 }
331
332 /*-----------------------------------------------------
333  * Returns 1 if the given format is valid according to
334  * the OpenVG specification, else 0.
335  *-----------------------------------------------------*/
336
337 int shIsValidImageFormat(VGImageFormat format)
338 {
339   SHint aOrderBit = (1 << 6);
340   SHint rgbOrderBit = (1 << 7);
341   SHint baseFormat = format & 0x1F;
342   SHint unorderedRgba = format & (~(aOrderBit | rgbOrderBit));
343   SHint isRgba = (baseFormat == VG_sRGBX_8888     ||
344                   baseFormat == VG_sRGBA_8888     ||
345                   baseFormat == VG_sRGBA_8888_PRE ||
346                   baseFormat == VG_sRGBA_5551     ||
347                   baseFormat == VG_sRGBA_4444     ||
348                   baseFormat == VG_lRGBX_8888     ||
349                   baseFormat == VG_lRGBA_8888     ||
350                   baseFormat == VG_lRGBA_8888_PRE);
351   
352   SHint check = isRgba ? unorderedRgba : format;
353   return check >= VG_sRGBX_8888 && check <= VG_BW_1;
354 }
355
356 /*-----------------------------------------------------
357  * Returns 1 if the given format is supported by this
358  * implementation
359  *-----------------------------------------------------*/
360
361 int shIsSupportedImageFormat(VGImageFormat format)
362 {
363   SHuint32 baseFormat = (format & 0x1F);
364   if (baseFormat == VG_sRGBA_8888_PRE ||
365       baseFormat == VG_lRGBA_8888_PRE ||
366       baseFormat == VG_BW_1)
367       return 0;
368
369   return 1;
370 }
371
372 /*--------------------------------------------------------
373  * Packs the pixel color components into memory at given
374  * address according to given format
375  *--------------------------------------------------------*/
376
377 void shStoreColor(SHColor *c, void *data, SHImageFormatDesc *f)
378 {
379   /*
380   TODO: unsupported formats:
381   - s and l both behave linearly
382   - 1-bit black & white (BW_1)
383   */
384
385   SHfloat l = 0.0f;
386   SHuint32 out = 0x0;
387
388   if (f->vgformat == VG_lL_8 || f->vgformat == VG_sL_8) {
389
390     /* Grayscale (luminosity) conversion as defined by the spec */
391     l = 0.2126f * c->r + 0.7152f * c->g + 0.0722f * c->r;
392     out = (SHuint32)(l * (SHfloat)f->rmax + 0.5f);
393
394   }else{
395
396     /* Pack color components */
397     out += ( ((SHuint32)(c->r * (SHfloat)f->rmax + 0.5f)) << f->rshift ) & f->rmask;
398     out += ( ((SHuint32)(c->g * (SHfloat)f->gmax + 0.5f)) << f->gshift ) & f->gmask;
399     out += ( ((SHuint32)(c->b * (SHfloat)f->bmax + 0.5f)) << f->bshift ) & f->bmask;
400     out += ( ((SHuint32)(c->a * (SHfloat)f->amax + 0.5f)) << f->ashift ) & f->amask;
401   }
402   
403   /* Store to buffer */
404   switch (f->bytes) {
405   case 4: *((SHuint32*)data) = (SHuint32)(out & 0xFFFFFFFF); break;
406   case 2: *((SHuint16*)data) = (SHuint16)(out & 0x0000FFFF); break;
407   case 1: *((SHuint8*)data)  = (SHuint8) (out & 0x000000FF); break;
408   }
409 }
410
411 /*---------------------------------------------------------
412  * Unpacks the pixel color components from memory at given
413  * address according to the given format
414  *---------------------------------------------------------*/
415
416 void shLoadColor(SHColor *c, const void *data, SHImageFormatDesc *f)
417 {
418   /*
419   TODO: unsupported formats:
420   - s and l both behave linearly
421   - 1-bit black & white (BW_1)
422   */
423
424   SHuint32 in = 0x0;
425   
426   /* Load from buffer */
427   switch (f->bytes) {
428   case 4: in = (SHuint32) *((SHuint32*)data); break;
429   case 2: in = (SHuint32) *((SHuint16*)data); break;
430   case 1: in = (SHuint32) *((SHuint8*)data); break;
431   }
432
433   /* Unpack color components */
434   c->r = (SHfloat)((in & f->rmask) >> f->rshift) / (SHfloat) f->rmax;
435   c->g = (SHfloat)((in & f->gmask) >> f->gshift) / (SHfloat) f->gmax;
436   c->b = (SHfloat)((in & f->bmask) >> f->bshift) / (SHfloat) f->bmax;
437   c->a = (SHfloat)((in & f->amask) >> f->ashift) / (SHfloat) f->amax;
438   
439   /* Initialize unused components to 1 */
440   if (f->amask == 0x0) { c->a = 1.0f; }
441   if (f->rmask == 0x0) { c->r = 1.0f; c->g = 1.0f; c->b = 1.0f; }
442 }
443
444 #endif // SH_NO_IMAGE
445
446 /*----------------------------------------------
447  * Color and Image constructors and destructors
448  *----------------------------------------------*/
449
450 void SHColor_ctor(SHColor *c)
451 {
452   c->r = 0.0f;
453   c->g = 0.0f;
454   c->b = 0.0f;
455   c->a = 0.0f;
456 }
457
458 void SHColor_dtor(SHColor *c) {
459 }
460
461 void SHImage_ctor(SHImage *i)
462 {
463   i->data = NULL;
464   i->width = 0;
465   i->height = 0;
466
467 #ifdef SH_NO_IMAGE
468   printf("ShivaVG: images not supported!");
469 #else
470   glGenTextures(1, &i->texture);
471 #endif
472 }
473
474 void SHImage_dtor(SHImage *i)
475 {
476   if (i->data != NULL)
477     free(i->data);
478
479 #ifdef SH_NO_IMAGE
480   printf("ShivaVG: images not supported!");
481 #else
482   if (glIsTexture(i->texture))
483     glDeleteTextures(1, &i->texture);
484 #endif
485 }
486
487 #ifndef SH_NO_IMAGE
488 /*--------------------------------------------------------
489  * Finds appropriate OpenGL texture size for the size of
490  * the given image
491  *--------------------------------------------------------*/
492
493 void shUpdateImageTextureSize(SHImage *i)
494 {
495   i->texwidth = i->width;
496   i->texheight = i->height;
497   i->texwidthK = 1.0f;
498   i->texheightK = 1.0f;
499   
500   /* Round size to nearest power of 2 */
501   /* TODO: might be dropped out if it works without  */
502   
503   /*i->texwidth = 1;
504   while (i->texwidth < i->width)
505     i->texwidth *= 2;
506   
507   i->texheight = 1;
508   while (i->texheight < i->height)
509     i->texheight *= 2;
510   
511   i->texwidthK  = (SHfloat)i->width  / i->texwidth;
512   i->texheightK = (SHfloat)i->height / i->texheight; */
513 }
514
515 /*--------------------------------------------------
516  * Downloads the image data from OpenVG into 
517  * an OpenGL texture
518  *--------------------------------------------------*/
519
520 void shUpdateImageTexture(SHImage *i, VGContext *c)
521 {
522   SHint potwidth;
523   SHint potheight;
524   SHint8 *potdata;
525
526   /* Find nearest power of two size */
527
528   potwidth = 1;
529   while (potwidth < i->width)
530     potwidth *= 2;
531   
532   potheight = 1;
533   while (potheight < i->height)
534     potheight *= 2;
535   
536   
537   /* Scale into a temp buffer if image not a power-of-two size (pot)
538      and non-power-of-two textures are not supported by OpenGL */  
539   
540   if ((i->width < potwidth || i->height < potheight) &&
541       !c->isGLAvailable_TextureNonPowerOfTwo) {
542     
543     potdata = (SHint8*)malloc( potwidth * potheight * i->fd.bytes );
544     if (!potdata) return;
545     
546     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
547     glPixelStorei(GL_PACK_ALIGNMENT, 1);
548     glBindTexture(GL_TEXTURE_2D, i->texture);
549     
550     
551     gluScaleImage(i->fd.glformat, i->width, i->height, i->fd.gltype, i->data,
552                   potwidth, potheight, i->fd.gltype, potdata);
553     
554     glTexImage2D(GL_TEXTURE_2D, 0, i->fd.glintformat, potwidth, potheight, 0,
555                  i->fd.glformat, i->fd.gltype, potdata);
556     
557     free(potdata);
558     return;
559   }
560   
561   /* Store pixels to texture */
562   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
563   glBindTexture(GL_TEXTURE_2D, i->texture);
564   glTexImage2D(GL_TEXTURE_2D, 0, i->fd.glintformat,
565                i->texwidth, i->texheight, 0,
566                i->fd.glformat, i->fd.gltype, i->data);
567 }
568 #endif // SH_NO_IMAGE
569
570 /*----------------------------------------------------------
571  * Creates a new image object and returns the handle to it
572  *----------------------------------------------------------*/
573
574 VG_API_CALL VGImage vgCreateImage(VGImageFormat format,
575                                   VGint width, VGint height,
576                                   VGbitfield allowedQuality)
577 {
578 #ifdef SH_NO_IMAGE
579   printf("ShivaVG: images not supported!");
580   return VG_INVALID_HANDLE;
581 #else
582   SHImage *i = NULL;
583   SHImageFormatDesc fd;
584   VG_GETCONTEXT(VG_INVALID_HANDLE);
585   
586   /* Reject invalid formats */
587   VG_RETURN_ERR_IF(!shIsValidImageFormat(format),
588                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
589                    VG_INVALID_HANDLE);
590   
591   /* Reject unsupported formats */
592   VG_RETURN_ERR_IF(!shIsSupportedImageFormat(format),
593                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
594                    VG_INVALID_HANDLE);
595   
596   /* Reject invalid sizes */
597   VG_RETURN_ERR_IF(width  <= 0 || width > SH_MAX_IMAGE_WIDTH ||
598                    height <= 0 || height > SH_MAX_IMAGE_HEIGHT ||
599                    width * height > SH_MAX_IMAGE_PIXELS,
600                    VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
601   
602   /* Check if byte size exceeds SH_MAX_IMAGE_BYTES */
603   shSetupImageFormat(format, &fd);
604   VG_RETURN_ERR_IF(width * height * fd.bytes > SH_MAX_IMAGE_BYTES,
605                    VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
606   
607   /* Reject invalid quality bits */
608   VG_RETURN_ERR_IF(allowedQuality &
609                    ~(VG_IMAGE_QUALITY_NONANTIALIASED |
610                      VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER),
611                    VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
612   
613   /* Create new image object */
614   SH_NEWOBJ(SHImage, i);
615   VG_RETURN_ERR_IF(!i, VG_OUT_OF_MEMORY_ERROR, VG_INVALID_HANDLE);
616   i->width = width;
617   i->height = height;
618   i->fd = fd;
619   
620   /* Allocate data memory */
621   shUpdateImageTextureSize(i);
622   i->data = (SHuint8*)malloc( i->texwidth * i->texheight * fd.bytes );
623   
624   if (i->data == NULL) {
625     SH_DELETEOBJ(SHImage, i);
626     VG_RETURN_ERR(VG_OUT_OF_MEMORY_ERROR, VG_INVALID_HANDLE); }
627   
628   /* Initialize data by zeroing-out */
629   memset(i->data, 1, width * height * fd.bytes);
630   shUpdateImageTexture(i, context);
631   
632   /* Add to resource list */
633   shImageArrayPushBack(&context->images, i);
634
635   VG_RETURN((VGImage)i);
636 #endif // SH_NO_IMAGE
637 }
638
639 VG_API_CALL void vgDestroyImage(VGImage image)
640 {
641 #ifdef SH_NO_IMAGE
642   printf("ShivaVG: images not supported!");
643 #else
644   SHint index;
645   VG_GETCONTEXT(VG_NO_RETVAL);
646   
647   /* Check if valid resource */
648   index = shImageArrayFind(&context->images, (SHImage*)image);
649   VG_RETURN_ERR_IF(index == -1, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
650   
651   /* Delete object and remove resource */
652   SH_DELETEOBJ(SHImage, (SHImage*)image);
653   shImageArrayRemoveAt(&context->images, index);
654
655   VG_RETURN(VG_NO_RETVAL);
656 #endif // SH_NO_IMAGE
657 }
658
659 /*---------------------------------------------------
660  * Clear given rectangle area in the image data with
661  * color set via vgSetfv(VG_CLEAR_COLOR, ...)
662  *---------------------------------------------------*/
663
664 VG_API_CALL void vgClearImage(VGImage image,
665                               VGint x, VGint y, VGint width, VGint height)
666 {
667 #ifdef SH_NO_IMAGE
668   printf("ShivaVG: images not supported!");
669 #else
670   SHImage *i;
671   SHColor clear;
672   SHuint8 *data;
673   SHint X,Y, ix, iy, dx, dy, stride;
674   VG_GETCONTEXT(VG_NO_RETVAL);
675   
676   VG_RETURN_ERR_IF(!shIsValidImage(context, image),
677                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
678   
679   /* TODO: check if image current render target */
680   
681   i = (SHImage*)image;
682   VG_RETURN_ERR_IF(width <= 0 || height <= 0,
683                    VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
684   
685   /* Nothing to do if target rectangle out of bounds */
686   if (x >= i->width || y >= i->height)
687     VG_RETURN(VG_NO_RETVAL);
688   if (x + width < 0 || y + height < 0)
689     VG_RETURN(VG_NO_RETVAL);
690
691   /* Clamp to image bounds */
692   ix = SH_MAX(x, 0); dx = ix - x;
693   iy = SH_MAX(y, 0); dy = iy - y;
694   width  = SH_MIN( width  - dx, i->width  - ix);
695   height = SH_MIN( height - dy, i->height - iy);
696   stride = i->texwidth * i->fd.bytes;
697   
698   /* Walk pixels and clear*/
699   clear = context->clearColor;
700   
701   for (Y=iy; Y<iy+height; ++Y) {
702     data = i->data + ( Y*stride + ix * i->fd.bytes );
703     
704     for (X=ix; X<ix+width; ++X) {
705       shStoreColor(&clear, data, &i->fd);
706       data += i->fd.bytes;
707     }}
708   
709   shUpdateImageTexture(i, context);
710
711   VG_RETURN(VG_NO_RETVAL);
712 #endif // SH_NO_IMAGE
713 }
714
715 #ifndef SH_NO_IMAGE
716
717 /*------------------------------------------------------------
718  * Generic function for copying a rectangle area of pixels
719  * of size (width,height) among two data buffers. The size of
720  * source (swidth,sheight) and destination (dwidth,dheight)
721  * images may vary as well as the source coordinates (sx,sy)
722  * and destination coordinates(dx, dy).
723  *------------------------------------------------------------*/
724
725 void shCopyPixels(SHuint8 *dst, VGImageFormat dstFormat, SHint dstStride,
726                   const SHuint8 *src, VGImageFormat srcFormat, SHint srcStride,
727                   SHint dwidth, SHint dheight, SHint swidth, SHint sheight,
728                   SHint dx, SHint dy, SHint sx, SHint sy,
729                   SHint width, SHint height)
730 {
731   SHint dxold, dyold;
732   SHint SX, SY, DX, DY;
733   const SHuint8 *SD;
734   SHuint8 *DD;
735   SHColor c;
736
737   SHImageFormatDesc dfd;
738   SHImageFormatDesc sfd;
739
740   /* Setup image format descriptors */
741   SH_ASSERT(shIsSupportedImageFormat(dstFormat));
742   SH_ASSERT(shIsSupportedImageFormat(srcFormat));
743   shSetupImageFormat(dstFormat, &dfd);
744   shSetupImageFormat(srcFormat, &sfd);
745
746   /*
747     In order to optimize the copying loop and remove the
748     if statements from it to check whether target pixel
749     is in the source and destination surface, we clamp
750     copy rectangle in advance. This is quite a tedious
751     task though. Here is a picture of the scene. Note that
752     (dx,dy) is actually an offset of the copy rectangle
753     (clamped to src surface) from the (0,0) point on dst
754     surface. A negative (dx,dy) (as in this picture) also
755     affects src coords of the copy rectangle which have
756     to be readjusted again (sx,sy,width,height).
757
758                           src
759     *----------------------*
760     | (sx,sy)  copy rect   |
761     | *-----------*        |
762     | |\(dx, dy)  |        |          dst
763     | | *------------------------------*
764     | | |xxxxxxxxx|        |           |
765     | | |xxxxxxxxx|        |           |
766     | *-----------*        |           |
767     |   |   (width,height) |           |
768     *----------------------*           |
769         |           (swidth,sheight)   |
770         *------------------------------*
771                                 (dwidth,dheight)
772   */
773
774   /* Cancel if copy rect out of src bounds */
775   if (sx >= swidth || sy >= sheight) return;
776   if (sx + width < 0 || sy + height < 0) return;
777   
778   /* Clamp copy rectangle to src bounds */
779   sx = SH_MAX(sx, 0);
780   sy = SH_MAX(sy, 0);
781   width = SH_MIN(width, swidth - sx);
782   height = SH_MIN(height, sheight - sy);
783   
784   /* Cancel if copy rect out of dst bounds */
785   if (dx >= dwidth || dy >= dheight) return;
786   if (dx + width < 0 || dy + height < 0) return;
787   
788   /* Clamp copy rectangle to dst bounds */
789   dxold = dx; dyold = dy;
790   dx = SH_MAX(dx, 0);
791   dy = SH_MAX(dy, 0);
792   sx += dx - dxold;
793   sy += dy - dyold;
794   width -= dx - dxold;
795   height -= dy - dyold;
796   width = SH_MIN(width, dwidth  - dx);
797   height = SH_MIN(height, dheight - dy);
798   
799   /* Calculate stride from format if not given */
800   if (dstStride == -1) dstStride = dwidth * dfd.bytes;
801   if (srcStride == -1) srcStride = swidth * sfd.bytes;
802   
803   if (srcFormat == dstFormat) {
804     
805     /* Walk pixels and copy */
806     for (SY=sy, DY=dy; SY < sy+height; ++SY, ++DY) {
807       SD = src + SY * srcStride + sx * sfd.bytes;
808       DD = dst + DY * dstStride + dx * dfd.bytes;
809       memcpy(DD, SD, width * sfd.bytes);
810     }
811     
812   }else{
813   
814     /* Walk pixels and copy */
815     for (SY=sy, DY=dy; SY < sy+height; ++SY, ++DY) {
816       SD = src + SY * srcStride + sx * sfd.bytes;
817       DD = dst + DY * dstStride + dx * dfd.bytes;
818       
819       for (SX=sx, DX=dx; SX < sx+width; ++SX, ++DX) {
820         shLoadColor(&c, SD, &sfd);
821         shStoreColor(&c, DD, &dfd);
822         SD += sfd.bytes; DD += dfd.bytes;
823       }}
824   }
825 }
826
827 #endif // SH_NO_IMAGE
828
829 /*---------------------------------------------------------
830  * Copies a rectangle area of pixels of size (width,height)
831  * from given data buffer to image surface at destination
832  * coordinates (x,y)
833  *---------------------------------------------------------*/
834
835 VG_API_CALL void vgImageSubData(VGImage image,
836                                 const void * data, VGint dataStride,
837                                 VGImageFormat dataFormat,
838                                 VGint x, VGint y, VGint width, VGint height)
839 {
840 #ifdef SH_NO_IMAGE
841   printf("ShivaVG: images not supported!");
842 #else
843   SHImage *i;
844   VG_GETCONTEXT(VG_NO_RETVAL);
845   
846   VG_RETURN_ERR_IF(!shIsValidImage(context, image),
847                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
848   
849   /* TODO: check if image current render target */
850   i = (SHImage*)image;
851   
852   /* Reject invalid formats */
853   VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
854                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
855                    VG_NO_RETVAL);
856   
857   /* Reject unsupported image formats */
858   VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
859                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
860                    VG_NO_RETVAL);
861   
862   VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
863                    VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
864   
865   /* TODO: check data array alignment */
866   
867   shCopyPixels(i->data, i->fd.vgformat, i->texwidth * i->fd.bytes,
868                data, dataFormat,dataStride,
869                i->width, i->height, width, height,
870                x, y, 0, 0, width, height);
871   
872   shUpdateImageTexture(i, context);
873
874   VG_RETURN(VG_NO_RETVAL);
875 #endif // SH_NO_IMAGE
876 }
877
878 /*---------------------------------------------------------
879  * Copies a rectangle area of pixels of size (width,height)
880  * from image surface at source coordinates (x,y) to given
881  * data buffer
882  *---------------------------------------------------------*/
883
884 VG_API_CALL void vgGetImageSubData(VGImage image,
885                                    void * data, VGint dataStride,
886                                    VGImageFormat dataFormat,
887                                    VGint x, VGint y,
888                                    VGint width, VGint height)
889 {
890 #ifdef SH_NO_IMAGE
891   printf("ShivaVG: images not supported!");
892 #else
893   SHImage *i;
894   VG_GETCONTEXT(VG_NO_RETVAL);
895   
896   VG_RETURN_ERR_IF(!shIsValidImage(context, image),
897                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
898   
899   /* TODO: check if image current render target */
900   i = (SHImage*)image;
901   
902   /* Reject invalid formats */
903   VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
904                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
905                    VG_NO_RETVAL);
906   
907   /* Reject unsupported formats */
908   VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
909                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
910                    VG_NO_RETVAL);
911   
912   VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
913                    VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
914   
915   /* TODO: check data array alignment */
916   
917   shCopyPixels(data, dataFormat, dataStride,
918                i->data, i->fd.vgformat, i->texwidth * i->fd.bytes,
919                width, height, i->width, i->height,
920                0,0,x,y,width,height);
921
922   VG_RETURN(VG_NO_RETVAL);
923 #endif // SH_NO_IMAGE
924 }
925
926 /*----------------------------------------------------------
927  * Copies a rectangle area of pixels of size (width,height)
928  * from src image surface at source coordinates (sx,sy) to
929  * dst image surface at destination cordinates (dx,dy)
930  *---------------------------------------------------------*/
931
932 VG_API_CALL void vgCopyImage(VGImage dst, VGint dx, VGint dy,
933                              VGImage src, VGint sx, VGint sy,
934                              VGint width, VGint height,
935                              VGboolean dither)
936 {
937 #ifdef SH_NO_IMAGE
938   printf("ShivaVG: images not supported!");
939 #else
940   SHImage *s, *d;
941   SHuint8 *pixels;
942
943   VG_GETCONTEXT(VG_NO_RETVAL);
944   
945   VG_RETURN_ERR_IF(!shIsValidImage(context, src) ||
946                    !shIsValidImage(context, dst),
947                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
948
949   /* TODO: check if images current render target */
950
951   s = (SHImage*)src; d = (SHImage*)dst;
952   VG_RETURN_ERR_IF(width <= 0 || height <= 0,
953                    VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
954
955   /* In order to perform copying in a cosistent fashion
956      we first copy to a temporary buffer and only then to
957      destination image */
958   
959   /* TODO: rather check first if the image is really
960      the same and whether the regions overlap. if not
961      we can copy directly */
962
963   pixels = (SHuint8*)malloc(width * height * s->fd.bytes);
964   SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
965
966   shCopyPixels(pixels, s->fd.vgformat, s->texwidth * s->fd.bytes,
967                s->data, s->fd.vgformat, s->texwidth * s->fd.bytes,
968                width, height, s->width, s->height,
969                0, 0, sx, sy, width, height);
970
971   shCopyPixels(d->data, d->fd.vgformat, d->texwidth * d->fd.bytes,
972                pixels, s->fd.vgformat, s->texwidth * s->fd.bytes,
973                d->width, d->height, width, height,
974                dx, dy, 0, 0, width, height);
975   
976   free(pixels);
977   
978   shUpdateImageTexture(d, context);
979
980   VG_RETURN(VG_NO_RETVAL);
981 #endif // SH_NO_IMAGE
982 }
983
984 /*---------------------------------------------------------
985  * Copies a rectangle area of pixels of size (width,height)
986  * from src image surface at source coordinates (sx,sy) to
987  * window surface at destination coordinates (dx,dy)
988  *---------------------------------------------------------*/
989
990 VG_API_CALL void vgSetPixels(VGint dx, VGint dy,
991                              VGImage src, VGint sx, VGint sy,
992                              VGint width, VGint height)
993 {
994 #ifdef SH_NO_IMAGE
995   printf("ShivaVG: images not supported!");
996 #else
997   SHImage *i;
998   SHuint8 *pixels;
999   SHImageFormatDesc winfd;
1000
1001   VG_GETCONTEXT(VG_NO_RETVAL);
1002   
1003   VG_RETURN_ERR_IF(!shIsValidImage(context, src),
1004                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1005   
1006   /* TODO: check if image current render target (requires EGL) */
1007
1008   i = (SHImage*)src;
1009   VG_RETURN_ERR_IF(width <= 0 || height <= 0,
1010                    VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
1011
1012   /* Setup window image format descriptor */
1013   /* TODO: this actually depends on the target framebuffer type
1014      if we really want the copy to be optimized */
1015   shSetupImageFormat(VG_sRGBA_8888, &winfd);
1016
1017   /* OpenGL doesn't allow us to use random stride. We have to
1018      manually copy the image data and write from a copy with
1019      normal row length (without power-of-two roundup pixels) */
1020
1021   pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1022   SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1023
1024   shCopyPixels(pixels, winfd.vgformat, -1,
1025                i->data, i->fd.vgformat, i->texwidth * i->fd.bytes,
1026                width, height, i->width, i->height,
1027                0,0,sx,sy, width, height);
1028
1029   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1030   glRasterPos2i(dx, dy);
1031   glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1032   glRasterPos2i(0,0);
1033   
1034   free(pixels);
1035
1036   VG_RETURN(VG_NO_RETVAL);
1037 #endif // SH_NO_IMAGE
1038 }
1039
1040 /*---------------------------------------------------------
1041  * Copies a rectangle area of pixels of size (width,height)
1042  * from given data buffer at source coordinates (sx,sy) to
1043  * window surface at destination coordinates (dx,dy)
1044  *---------------------------------------------------------*/
1045
1046 VG_API_CALL void vgWritePixels(const void * data, VGint dataStride,
1047                                VGImageFormat dataFormat,
1048                                VGint dx, VGint dy,
1049                                VGint width, VGint height)
1050 {
1051 #ifdef SH_NO_IMAGE
1052   printf("ShivaVG: images not supported!");
1053 #else
1054   SHuint8 *pixels;
1055   SHImageFormatDesc winfd;
1056
1057   VG_GETCONTEXT(VG_NO_RETVAL);
1058
1059   /* Reject invalid formats */
1060   VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
1061                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1062                    VG_NO_RETVAL);
1063   
1064   /* Reject unsupported formats */
1065   VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
1066                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1067                    VG_NO_RETVAL);
1068
1069   /* TODO: check output data array alignment */
1070   
1071   VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
1072                    VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
1073
1074   /* Setup window image format descriptor */
1075   /* TODO: this actually depends on the target framebuffer type
1076      if we really want the copy to be optimized */
1077   shSetupImageFormat(VG_sRGBA_8888, &winfd);
1078
1079   /* OpenGL doesn't allow us to use random stride. We have to
1080      manually copy the image data and write from a copy with
1081      normal row length */
1082
1083   pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1084   SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1085   
1086   shCopyPixels(pixels, winfd.vgformat, -1,
1087                (SHuint8*)data, dataFormat, dataStride,
1088                width, height, width, height,
1089                0,0,0,0, width, height);
1090   
1091   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1092   glRasterPos2i(dx, dy);
1093   glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1094   glRasterPos2i(0,0);
1095   
1096   free(pixels);
1097
1098   VG_RETURN(VG_NO_RETVAL);
1099 #endif // SH_NO_IMAGE
1100 }
1101
1102 /*-----------------------------------------------------------
1103  * Copies a rectangle area of pixels of size (width, height)
1104  * from window surface at source coordinates (sx, sy) to
1105  * image surface at destination coordinates (dx, dy)
1106  *-----------------------------------------------------------*/
1107
1108 VG_API_CALL void vgGetPixels(VGImage dst, VGint dx, VGint dy,
1109                              VGint sx, VGint sy,
1110                              VGint width, VGint height)
1111 {
1112 #ifdef SH_NO_IMAGE
1113   printf("ShivaVG: images not supported!");
1114 #else
1115   SHImage *i;
1116   SHuint8 *pixels;
1117   SHImageFormatDesc winfd;
1118   VG_GETCONTEXT(VG_NO_RETVAL);
1119   
1120   VG_RETURN_ERR_IF(!shIsValidImage(context, dst),
1121                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1122   
1123    /* TODO: check if image current render target */
1124
1125   i = (SHImage*)dst;
1126   VG_RETURN_ERR_IF(width <= 0 || height <= 0,
1127                    VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
1128
1129   /* Setup window image format descriptor */
1130   /* TODO: this actually depends on the target framebuffer type
1131      if we really want the copy to be optimized */
1132   shSetupImageFormat(VG_sRGBA_8888, &winfd);
1133   
1134   /* OpenGL doesn't allow us to read to random destination
1135      coordinates nor using random stride. We have to
1136      read first and then manually copy to the image data */
1137
1138   pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1139   SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1140
1141   glPixelStorei(GL_PACK_ALIGNMENT, 1);
1142   glReadPixels(sx, sy, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1143   
1144   shCopyPixels(i->data, i->fd.vgformat, i->texwidth * i->fd.bytes,
1145                pixels, winfd.vgformat, -1,
1146                i->width, i->height, width, height,
1147                dx, dy, 0, 0, width, height);
1148
1149   free(pixels);
1150   
1151   shUpdateImageTexture(i, context);
1152
1153   VG_RETURN(VG_NO_RETVAL);
1154 #endif // SH_NO_IMAGE
1155 }
1156
1157 /*-----------------------------------------------------------
1158  * Copies a rectangle area of pixels of size (width, height)
1159  * from window surface at source coordinates (sx, sy) to
1160  * to given output data buffer.
1161  *-----------------------------------------------------------*/
1162
1163 VG_API_CALL void vgReadPixels(void * data, VGint dataStride,
1164                               VGImageFormat dataFormat,
1165                               VGint sx, VGint sy,
1166                               VGint width, VGint height)
1167 {
1168 #ifdef SH_NO_IMAGE
1169   printf("ShivaVG: images not supported!");
1170 #else
1171   SHuint8 *pixels;
1172   SHImageFormatDesc winfd;
1173   VG_GETCONTEXT(VG_NO_RETVAL);
1174
1175   /* Reject invalid formats */
1176   VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
1177                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1178                    VG_NO_RETVAL);
1179   
1180   /* Reject unsupported image formats */
1181   VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
1182                    VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1183                    VG_NO_RETVAL);
1184
1185   /* TODO: check output data array alignment */
1186   
1187   VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
1188                    VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
1189
1190   /* Setup window image format descriptor */
1191   /* TODO: this actually depends on the target framebuffer type
1192      if we really want the copy to be optimized */
1193   shSetupImageFormat(VG_sRGBA_8888, &winfd);
1194
1195   /* OpenGL doesn't allow random data stride. We have to
1196      read first and then manually copy to the output buffer */
1197
1198   pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1199   SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1200
1201   glPixelStorei(GL_PACK_ALIGNMENT, 1);
1202   glReadPixels(sx, sy, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1203   
1204   shCopyPixels(data, dataFormat, dataStride,
1205                pixels, winfd.vgformat, -1,
1206                width, height, width, height,
1207                0, 0, 0, 0, width, height);
1208
1209   free(pixels);
1210
1211   VG_RETURN(VG_NO_RETVAL);
1212 #endif // SH_NO_IMAGE
1213 }
1214
1215 /*----------------------------------------------------------
1216  * Copies a rectangle area of pixels of size (width,height)
1217  * from window surface at source coordinates (sx,sy) to
1218  * windows surface at destination cordinates (dx,dy)
1219  *---------------------------------------------------------*/
1220
1221 VG_API_CALL void vgCopyPixels(VGint dx, VGint dy,
1222                               VGint sx, VGint sy,
1223                               VGint width, VGint height)
1224 {
1225 #ifdef SH_NO_IMAGE
1226   printf("ShivaVG: images not supported!");
1227 #else
1228   VG_GETCONTEXT(VG_NO_RETVAL);
1229   
1230   VG_RETURN_ERR_IF(width <= 0 || height <= 0,
1231                    VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
1232   
1233   glPixelStorei(GL_PACK_ALIGNMENT, 1);
1234   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1235   glRasterPos2i(dx, dy);
1236   glCopyPixels(sx, sy, width, height, GL_COLOR);
1237   glRasterPos2i(0, 0);
1238
1239   VG_RETURN(VG_NO_RETVAL);
1240 #endif // SH_NO_IMAGE
1241 }
1242
1243 VG_API_CALL VGImage vgChildImage(VGImage parent,
1244                                  VGint x, VGint y, VGint width, VGint height)
1245 {
1246   return VG_INVALID_HANDLE;
1247 }
1248
1249 VG_API_CALL VGImage vgGetParent(VGImage image)
1250 {
1251   return VG_INVALID_HANDLE;
1252 }
1253
1254 VG_API_CALL void vgColorMatrix(VGImage dst, VGImage src,
1255                                const VGfloat * matrix)
1256 {
1257 }
1258
1259 VG_API_CALL void vgConvolve(VGImage dst, VGImage src,
1260                             VGint kernelWidth, VGint kernelHeight,
1261                             VGint shiftX, VGint shiftY,
1262                             const VGshort * kernel,
1263                             VGfloat scale,
1264                             VGfloat bias,
1265                             VGTilingMode tilingMode)
1266 {
1267 }
1268
1269 VG_API_CALL void vgSeparableConvolve(VGImage dst, VGImage src,
1270                                      VGint kernelWidth,
1271                                      VGint kernelHeight,
1272                                      VGint shiftX, VGint shiftY,
1273                                      const VGshort * kernelX,
1274                                      const VGshort * kernelY,
1275                                      VGfloat scale,
1276                                      VGfloat bias,
1277                                      VGTilingMode tilingMode)
1278 {
1279 }
1280
1281 VG_API_CALL void vgGaussianBlur(VGImage dst, VGImage src,
1282                                 VGfloat stdDeviationX,
1283                                 VGfloat stdDeviationY,
1284                                 VGTilingMode tilingMode)
1285 {
1286 }
1287
1288 VG_API_CALL void vgLookup(VGImage dst, VGImage src,
1289                           const VGubyte * redLUT,
1290                           const VGubyte * greenLUT,
1291                           const VGubyte * blueLUT,
1292                           const VGubyte * alphaLUT,
1293                           VGboolean outputLinear,
1294                           VGboolean outputPremultiplied)
1295 {
1296 }
1297
1298 VG_API_CALL void vgLookupSingle(VGImage dst, VGImage src,
1299                                 const VGuint * lookupTable,
1300                                 VGImageChannel sourceChannel,
1301                                 VGboolean outputLinear,
1302                                 VGboolean outputPremultiplied)
1303 {
1304 }