2 * Copyright (c) 2007 Ivan Leben
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.
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.
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
21 #include <vg/openvg.h>
23 #include "shContext.h"
27 #define _ITEM_T SHColor
28 #define _ARRAY_T SHColorArray
29 #define _FUNC_T shColorArray
31 #define _COMPARE_T(c1,c2) 0
32 #include "shArrayBase.h"
34 #define _ITEM_T SHImage*
35 #define _ARRAY_T SHImageArray
36 #define _FUNC_T shImageArray
38 #include "shArrayBase.h"
42 /*-----------------------------------------------------------
43 * Prepares the proper pixel pack/unpack info for the given
44 * OpenVG image format.
45 *-----------------------------------------------------------*/
47 void shSetupImageFormat(VGImageFormat vg, SHImageFormatDesc *f)
55 /* Store VG format name */
58 /* Check if alpha on MSB or colors in BGR order */
59 amsbBit = ((vg & (1 << 6)) >> 6);
60 bgrBit = ((vg & (1 << 7)) >> 7);
62 /* Find component ordering and size */
65 case 0: /* VG_sRGBX_8888 */
66 case 7: /* VG_lRGBX_8888 */
68 f->rmask = 0xFF000000;
71 f->gmask = 0x00FF0000;
74 f->bmask = 0x0000FF00;
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 */
86 f->rmask = 0xFF000000;
89 f->gmask = 0x00FF0000;
92 f->bmask = 0x0000FF00;
95 f->amask = 0x000000FF;
99 case 3: /* VG_sRGB_565 */
114 case 4: /* VG_sRGBA_5551 */
129 case 5: /* VG_sRGBA_4444 */
144 case 6: /* VG_sL_8 */
145 case 10: /* VG_lL_8 */
160 case 11: /* VG_A_8 */
175 case 12: /* VG_BW_1 */
192 /* Check for A,X at MSB */
200 f->ashift = f->bytes * 8 - abits;
205 f->amask <<= f->bytes * 8 - abits;
208 /* Check for BGR ordering */
212 f->bshift = f->rshift;
220 /* Find proper mapping to OpenGL formats */
226 case VG_sRGBA_8888_PRE:
228 case VG_lRGBA_8888_PRE:
230 f->glintformat = GL_RGBA;
232 if (amsbBit == 0 && bgrBit == 0) {
233 f->glformat = GL_RGBA;
234 f->gltype = GL_UNSIGNED_INT_8_8_8_8;
236 }else if (amsbBit == 1 && bgrBit == 0) {
237 f->glformat = GL_BGRA;
238 f->gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
240 }else if (amsbBit == 0 && bgrBit == 1) {
241 f->glformat = GL_BGRA;
242 f->gltype = GL_UNSIGNED_INT_8_8_8_8;
244 }else if (amsbBit == 1 && bgrBit == 1) {
245 f->glformat = GL_RGBA;
246 f->gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
252 f->glintformat = GL_RGBA;
254 if (amsbBit == 0 && bgrBit == 0) {
255 f->glformat = GL_RGBA;
256 f->gltype = GL_UNSIGNED_SHORT_5_5_5_1;
258 }else if (amsbBit == 1 && bgrBit == 0) {
259 f->glformat = GL_BGRA;
260 f->gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
262 }else if (amsbBit == 0 && bgrBit == 1) {
263 f->glformat = GL_BGRA;
264 f->gltype = GL_UNSIGNED_SHORT_5_5_5_1;
266 }else if (amsbBit == 1 && bgrBit == 1) {
267 f->glformat = GL_RGBA;
268 f->gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
274 f->glintformat = GL_RGBA;
276 if (amsbBit == 0 && bgrBit == 0) {
277 f->glformat = GL_RGBA;
278 f->gltype = GL_UNSIGNED_SHORT_4_4_4_4;
280 }else if (amsbBit == 1 && bgrBit == 0) {
281 f->glformat = GL_BGRA;
282 f->gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV;
284 }else if (amsbBit == 0 && bgrBit == 1) {
285 f->glformat = GL_BGRA;
286 f->gltype = GL_UNSIGNED_SHORT_4_4_4_4;
288 }else if (amsbBit == 1 && bgrBit == 1) {
289 f->glformat = GL_RGBA;
290 f->gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV;
296 f->glintformat = GL_RGB;
299 f->glformat = GL_RGB;
300 f->gltype = GL_UNSIGNED_SHORT_5_6_5;
302 }else if (bgrBit == 1) {
303 f->glformat = GL_RGB;
304 f->gltype = GL_UNSIGNED_SHORT_5_6_5;
311 f->glintformat = GL_LUMINANCE;
312 f->glformat = GL_LUMINANCE;
313 f->gltype = GL_UNSIGNED_BYTE;
318 f->glintformat = GL_ALPHA;
319 f->glformat = GL_ALPHA;
320 f->gltype = GL_UNSIGNED_BYTE;
332 /*-----------------------------------------------------
333 * Returns 1 if the given format is valid according to
334 * the OpenVG specification, else 0.
335 *-----------------------------------------------------*/
337 int shIsValidImageFormat(VGImageFormat format)
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);
352 SHint check = isRgba ? unorderedRgba : format;
353 return check >= VG_sRGBX_8888 && check <= VG_BW_1;
356 /*-----------------------------------------------------
357 * Returns 1 if the given format is supported by this
359 *-----------------------------------------------------*/
361 int shIsSupportedImageFormat(VGImageFormat format)
363 SHuint32 baseFormat = (format & 0x1F);
364 if (baseFormat == VG_sRGBA_8888_PRE ||
365 baseFormat == VG_lRGBA_8888_PRE ||
366 baseFormat == VG_BW_1)
372 /*--------------------------------------------------------
373 * Packs the pixel color components into memory at given
374 * address according to given format
375 *--------------------------------------------------------*/
377 void shStoreColor(SHColor *c, void *data, SHImageFormatDesc *f)
380 TODO: unsupported formats:
381 - s and l both behave linearly
382 - 1-bit black & white (BW_1)
388 if (f->vgformat == VG_lL_8 || f->vgformat == VG_sL_8) {
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);
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;
403 /* Store to buffer */
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;
411 /*---------------------------------------------------------
412 * Unpacks the pixel color components from memory at given
413 * address according to the given format
414 *---------------------------------------------------------*/
416 void shLoadColor(SHColor *c, const void *data, SHImageFormatDesc *f)
419 TODO: unsupported formats:
420 - s and l both behave linearly
421 - 1-bit black & white (BW_1)
426 /* Load from buffer */
428 case 4: in = (SHuint32) *((SHuint32*)data); break;
429 case 2: in = (SHuint32) *((SHuint16*)data); break;
430 case 1: in = (SHuint32) *((SHuint8*)data); break;
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;
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; }
444 #endif // SH_NO_IMAGE
446 /*----------------------------------------------
447 * Color and Image constructors and destructors
448 *----------------------------------------------*/
450 void SHColor_ctor(SHColor *c)
458 void SHColor_dtor(SHColor *c) {
461 void SHImage_ctor(SHImage *i)
468 printf("ShivaVG: images not supported!");
470 glGenTextures(1, &i->texture);
474 void SHImage_dtor(SHImage *i)
480 printf("ShivaVG: images not supported!");
482 if (glIsTexture(i->texture))
483 glDeleteTextures(1, &i->texture);
488 /*--------------------------------------------------------
489 * Finds appropriate OpenGL texture size for the size of
491 *--------------------------------------------------------*/
493 void shUpdateImageTextureSize(SHImage *i)
495 i->texwidth = i->width;
496 i->texheight = i->height;
498 i->texheightK = 1.0f;
500 /* Round size to nearest power of 2 */
501 /* TODO: might be dropped out if it works without */
504 while (i->texwidth < i->width)
508 while (i->texheight < i->height)
511 i->texwidthK = (SHfloat)i->width / i->texwidth;
512 i->texheightK = (SHfloat)i->height / i->texheight; */
515 /*--------------------------------------------------
516 * Downloads the image data from OpenVG into
518 *--------------------------------------------------*/
520 void shUpdateImageTexture(SHImage *i, VGContext *c)
526 /* Find nearest power of two size */
529 while (potwidth < i->width)
533 while (potheight < i->height)
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 */
540 if ((i->width < potwidth || i->height < potheight) &&
541 !c->isGLAvailable_TextureNonPowerOfTwo) {
543 potdata = (SHint8*)malloc( potwidth * potheight * i->fd.bytes );
544 if (!potdata) return;
546 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
547 glPixelStorei(GL_PACK_ALIGNMENT, 1);
548 glBindTexture(GL_TEXTURE_2D, i->texture);
551 gluScaleImage(i->fd.glformat, i->width, i->height, i->fd.gltype, i->data,
552 potwidth, potheight, i->fd.gltype, potdata);
554 glTexImage2D(GL_TEXTURE_2D, 0, i->fd.glintformat, potwidth, potheight, 0,
555 i->fd.glformat, i->fd.gltype, potdata);
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);
568 #endif // SH_NO_IMAGE
570 /*----------------------------------------------------------
571 * Creates a new image object and returns the handle to it
572 *----------------------------------------------------------*/
574 VG_API_CALL VGImage vgCreateImage(VGImageFormat format,
575 VGint width, VGint height,
576 VGbitfield allowedQuality)
579 printf("ShivaVG: images not supported!");
580 return VG_INVALID_HANDLE;
583 SHImageFormatDesc fd;
584 VG_GETCONTEXT(VG_INVALID_HANDLE);
586 /* Reject invalid formats */
587 VG_RETURN_ERR_IF(!shIsValidImageFormat(format),
588 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
591 /* Reject unsupported formats */
592 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(format),
593 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
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);
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);
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);
613 /* Create new image object */
614 SH_NEWOBJ(SHImage, i);
615 VG_RETURN_ERR_IF(!i, VG_OUT_OF_MEMORY_ERROR, VG_INVALID_HANDLE);
620 /* Allocate data memory */
621 shUpdateImageTextureSize(i);
622 i->data = (SHuint8*)malloc( i->texwidth * i->texheight * fd.bytes );
624 if (i->data == NULL) {
625 SH_DELETEOBJ(SHImage, i);
626 VG_RETURN_ERR(VG_OUT_OF_MEMORY_ERROR, VG_INVALID_HANDLE); }
628 /* Initialize data by zeroing-out */
629 memset(i->data, 1, width * height * fd.bytes);
630 shUpdateImageTexture(i, context);
632 /* Add to resource list */
633 shImageArrayPushBack(&context->images, i);
635 VG_RETURN((VGImage)i);
636 #endif // SH_NO_IMAGE
639 VG_API_CALL void vgDestroyImage(VGImage image)
642 printf("ShivaVG: images not supported!");
645 VG_GETCONTEXT(VG_NO_RETVAL);
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);
651 /* Delete object and remove resource */
652 SH_DELETEOBJ(SHImage, (SHImage*)image);
653 shImageArrayRemoveAt(&context->images, index);
655 VG_RETURN(VG_NO_RETVAL);
656 #endif // SH_NO_IMAGE
659 /*---------------------------------------------------
660 * Clear given rectangle area in the image data with
661 * color set via vgSetfv(VG_CLEAR_COLOR, ...)
662 *---------------------------------------------------*/
664 VG_API_CALL void vgClearImage(VGImage image,
665 VGint x, VGint y, VGint width, VGint height)
668 printf("ShivaVG: images not supported!");
673 SHint X,Y, ix, iy, dx, dy, stride;
674 VG_GETCONTEXT(VG_NO_RETVAL);
676 VG_RETURN_ERR_IF(!shIsValidImage(context, image),
677 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
679 /* TODO: check if image current render target */
682 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
683 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
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);
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;
698 /* Walk pixels and clear*/
699 clear = context->clearColor;
701 for (Y=iy; Y<iy+height; ++Y) {
702 data = i->data + ( Y*stride + ix * i->fd.bytes );
704 for (X=ix; X<ix+width; ++X) {
705 shStoreColor(&clear, data, &i->fd);
709 shUpdateImageTexture(i, context);
711 VG_RETURN(VG_NO_RETVAL);
712 #endif // SH_NO_IMAGE
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 *------------------------------------------------------------*/
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)
732 SHint SX, SY, DX, DY;
737 SHImageFormatDesc dfd;
738 SHImageFormatDesc sfd;
740 /* Setup image format descriptors */
741 SH_ASSERT(shIsSupportedImageFormat(dstFormat));
742 SH_ASSERT(shIsSupportedImageFormat(srcFormat));
743 shSetupImageFormat(dstFormat, &dfd);
744 shSetupImageFormat(srcFormat, &sfd);
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).
759 *----------------------*
760 | (sx,sy) copy rect |
763 | | *------------------------------*
767 | | (width,height) | |
768 *----------------------* |
770 *------------------------------*
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;
778 /* Clamp copy rectangle to src bounds */
781 width = SH_MIN(width, swidth - sx);
782 height = SH_MIN(height, sheight - sy);
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;
788 /* Clamp copy rectangle to dst bounds */
789 dxold = dx; dyold = dy;
795 height -= dy - dyold;
796 width = SH_MIN(width, dwidth - dx);
797 height = SH_MIN(height, dheight - dy);
799 /* Calculate stride from format if not given */
800 if (dstStride == -1) dstStride = dwidth * dfd.bytes;
801 if (srcStride == -1) srcStride = swidth * sfd.bytes;
803 if (srcFormat == dstFormat) {
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);
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;
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;
827 #endif // SH_NO_IMAGE
829 /*---------------------------------------------------------
830 * Copies a rectangle area of pixels of size (width,height)
831 * from given data buffer to image surface at destination
833 *---------------------------------------------------------*/
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)
841 printf("ShivaVG: images not supported!");
844 VG_GETCONTEXT(VG_NO_RETVAL);
846 VG_RETURN_ERR_IF(!shIsValidImage(context, image),
847 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
849 /* TODO: check if image current render target */
852 /* Reject invalid formats */
853 VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
854 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
857 /* Reject unsupported image formats */
858 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
859 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
862 VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
863 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
865 /* TODO: check data array alignment */
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);
872 shUpdateImageTexture(i, context);
874 VG_RETURN(VG_NO_RETVAL);
875 #endif // SH_NO_IMAGE
878 /*---------------------------------------------------------
879 * Copies a rectangle area of pixels of size (width,height)
880 * from image surface at source coordinates (x,y) to given
882 *---------------------------------------------------------*/
884 VG_API_CALL void vgGetImageSubData(VGImage image,
885 void * data, VGint dataStride,
886 VGImageFormat dataFormat,
888 VGint width, VGint height)
891 printf("ShivaVG: images not supported!");
894 VG_GETCONTEXT(VG_NO_RETVAL);
896 VG_RETURN_ERR_IF(!shIsValidImage(context, image),
897 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
899 /* TODO: check if image current render target */
902 /* Reject invalid formats */
903 VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
904 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
907 /* Reject unsupported formats */
908 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
909 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
912 VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
913 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
915 /* TODO: check data array alignment */
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);
922 VG_RETURN(VG_NO_RETVAL);
923 #endif // SH_NO_IMAGE
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 *---------------------------------------------------------*/
932 VG_API_CALL void vgCopyImage(VGImage dst, VGint dx, VGint dy,
933 VGImage src, VGint sx, VGint sy,
934 VGint width, VGint height,
938 printf("ShivaVG: images not supported!");
943 VG_GETCONTEXT(VG_NO_RETVAL);
945 VG_RETURN_ERR_IF(!shIsValidImage(context, src) ||
946 !shIsValidImage(context, dst),
947 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
949 /* TODO: check if images current render target */
951 s = (SHImage*)src; d = (SHImage*)dst;
952 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
953 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
955 /* In order to perform copying in a cosistent fashion
956 we first copy to a temporary buffer and only then to
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 */
963 pixels = (SHuint8*)malloc(width * height * s->fd.bytes);
964 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
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);
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);
978 shUpdateImageTexture(d, context);
980 VG_RETURN(VG_NO_RETVAL);
981 #endif // SH_NO_IMAGE
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 *---------------------------------------------------------*/
990 VG_API_CALL void vgSetPixels(VGint dx, VGint dy,
991 VGImage src, VGint sx, VGint sy,
992 VGint width, VGint height)
995 printf("ShivaVG: images not supported!");
999 SHImageFormatDesc winfd;
1001 VG_GETCONTEXT(VG_NO_RETVAL);
1003 VG_RETURN_ERR_IF(!shIsValidImage(context, src),
1004 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1006 /* TODO: check if image current render target (requires EGL) */
1009 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
1010 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
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);
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) */
1021 pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1022 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
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);
1029 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1030 glRasterPos2i(dx, dy);
1031 glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1036 VG_RETURN(VG_NO_RETVAL);
1037 #endif // SH_NO_IMAGE
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 *---------------------------------------------------------*/
1046 VG_API_CALL void vgWritePixels(const void * data, VGint dataStride,
1047 VGImageFormat dataFormat,
1049 VGint width, VGint height)
1052 printf("ShivaVG: images not supported!");
1055 SHImageFormatDesc winfd;
1057 VG_GETCONTEXT(VG_NO_RETVAL);
1059 /* Reject invalid formats */
1060 VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
1061 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1064 /* Reject unsupported formats */
1065 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
1066 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1069 /* TODO: check output data array alignment */
1071 VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
1072 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
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);
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 */
1083 pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1084 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1086 shCopyPixels(pixels, winfd.vgformat, -1,
1087 (SHuint8*)data, dataFormat, dataStride,
1088 width, height, width, height,
1089 0,0,0,0, width, height);
1091 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1092 glRasterPos2i(dx, dy);
1093 glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1098 VG_RETURN(VG_NO_RETVAL);
1099 #endif // SH_NO_IMAGE
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 *-----------------------------------------------------------*/
1108 VG_API_CALL void vgGetPixels(VGImage dst, VGint dx, VGint dy,
1110 VGint width, VGint height)
1113 printf("ShivaVG: images not supported!");
1117 SHImageFormatDesc winfd;
1118 VG_GETCONTEXT(VG_NO_RETVAL);
1120 VG_RETURN_ERR_IF(!shIsValidImage(context, dst),
1121 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1123 /* TODO: check if image current render target */
1126 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
1127 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
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);
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 */
1138 pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1139 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1141 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1142 glReadPixels(sx, sy, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
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);
1151 shUpdateImageTexture(i, context);
1153 VG_RETURN(VG_NO_RETVAL);
1154 #endif // SH_NO_IMAGE
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 *-----------------------------------------------------------*/
1163 VG_API_CALL void vgReadPixels(void * data, VGint dataStride,
1164 VGImageFormat dataFormat,
1166 VGint width, VGint height)
1169 printf("ShivaVG: images not supported!");
1172 SHImageFormatDesc winfd;
1173 VG_GETCONTEXT(VG_NO_RETVAL);
1175 /* Reject invalid formats */
1176 VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
1177 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1180 /* Reject unsupported image formats */
1181 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
1182 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1185 /* TODO: check output data array alignment */
1187 VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
1188 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
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);
1195 /* OpenGL doesn't allow random data stride. We have to
1196 read first and then manually copy to the output buffer */
1198 pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1199 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1201 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1202 glReadPixels(sx, sy, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1204 shCopyPixels(data, dataFormat, dataStride,
1205 pixels, winfd.vgformat, -1,
1206 width, height, width, height,
1207 0, 0, 0, 0, width, height);
1211 VG_RETURN(VG_NO_RETVAL);
1212 #endif // SH_NO_IMAGE
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 *---------------------------------------------------------*/
1221 VG_API_CALL void vgCopyPixels(VGint dx, VGint dy,
1223 VGint width, VGint height)
1226 printf("ShivaVG: images not supported!");
1228 VG_GETCONTEXT(VG_NO_RETVAL);
1230 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
1231 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
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);
1239 VG_RETURN(VG_NO_RETVAL);
1240 #endif // SH_NO_IMAGE
1243 VG_API_CALL VGImage vgChildImage(VGImage parent,
1244 VGint x, VGint y, VGint width, VGint height)
1246 return VG_INVALID_HANDLE;
1249 VG_API_CALL VGImage vgGetParent(VGImage image)
1251 return VG_INVALID_HANDLE;
1254 VG_API_CALL void vgColorMatrix(VGImage dst, VGImage src,
1255 const VGfloat * matrix)
1259 VG_API_CALL void vgConvolve(VGImage dst, VGImage src,
1260 VGint kernelWidth, VGint kernelHeight,
1261 VGint shiftX, VGint shiftY,
1262 const VGshort * kernel,
1265 VGTilingMode tilingMode)
1269 VG_API_CALL void vgSeparableConvolve(VGImage dst, VGImage src,
1272 VGint shiftX, VGint shiftY,
1273 const VGshort * kernelX,
1274 const VGshort * kernelY,
1277 VGTilingMode tilingMode)
1281 VG_API_CALL void vgGaussianBlur(VGImage dst, VGImage src,
1282 VGfloat stdDeviationX,
1283 VGfloat stdDeviationY,
1284 VGTilingMode tilingMode)
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)
1298 VG_API_CALL void vgLookupSingle(VGImage dst, VGImage src,
1299 const VGuint * lookupTable,
1300 VGImageChannel sourceChannel,
1301 VGboolean outputLinear,
1302 VGboolean outputPremultiplied)