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"
41 /*-----------------------------------------------------------
42 * Prepares the proper pixel pack/unpack info for the given
43 * OpenVG image format.
44 *-----------------------------------------------------------*/
46 void shSetupImageFormat(VGImageFormat vg, SHImageFormatDesc *f)
54 /* Store VG format name */
57 /* Check if alpha on MSB or colors in BGR order */
58 amsbBit = ((vg & (1 << 6)) >> 6);
59 bgrBit = ((vg & (1 << 7)) >> 7);
61 /* Find component ordering and size */
64 case 0: /* VG_sRGBX_8888 */
65 case 7: /* VG_lRGBX_8888 */
67 f->rmask = 0xFF000000;
70 f->gmask = 0x00FF0000;
73 f->bmask = 0x0000FF00;
80 case 1: /* VG_sRGBA_8888 */
81 case 2: /* VG_sRGBA_8888_PRE */
82 case 8: /* VG_lRGBA_8888 */
83 case 9: /* VG_lRGBA_8888_PRE */
85 f->rmask = 0xFF000000;
88 f->gmask = 0x00FF0000;
91 f->bmask = 0x0000FF00;
94 f->amask = 0x000000FF;
98 case 3: /* VG_sRGB_565 */
113 case 4: /* VG_sRGBA_5551 */
128 case 5: /* VG_sRGBA_4444 */
143 case 6: /* VG_sL_8 */
144 case 10: /* VG_lL_8 */
159 case 11: /* VG_A_8 */
174 case 12: /* VG_BW_1 */
191 /* Check for A,X at MSB */
199 f->ashift = f->bytes * 8 - abits;
204 f->amask <<= f->bytes * 8 - abits;
207 /* Check for BGR ordering */
211 f->bshift = f->rshift;
219 /* Find proper mapping to OpenGL formats */
225 case VG_sRGBA_8888_PRE:
227 case VG_lRGBA_8888_PRE:
229 f->glintformat = GL_RGBA;
231 if (amsbBit == 0 && bgrBit == 0) {
232 f->glformat = GL_RGBA;
233 f->gltype = GL_UNSIGNED_INT_8_8_8_8;
235 }else if (amsbBit == 1 && bgrBit == 0) {
236 f->glformat = GL_BGRA;
237 f->gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
239 }else if (amsbBit == 0 && bgrBit == 1) {
240 f->glformat = GL_BGRA;
241 f->gltype = GL_UNSIGNED_INT_8_8_8_8;
243 }else if (amsbBit == 1 && bgrBit == 1) {
244 f->glformat = GL_RGBA;
245 f->gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
251 f->glintformat = GL_RGBA;
253 if (amsbBit == 0 && bgrBit == 0) {
254 f->glformat = GL_RGBA;
255 f->gltype = GL_UNSIGNED_SHORT_5_5_5_1;
257 }else if (amsbBit == 1 && bgrBit == 0) {
258 f->glformat = GL_BGRA;
259 f->gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
261 }else if (amsbBit == 0 && bgrBit == 1) {
262 f->glformat = GL_BGRA;
263 f->gltype = GL_UNSIGNED_SHORT_5_5_5_1;
265 }else if (amsbBit == 1 && bgrBit == 1) {
266 f->glformat = GL_RGBA;
267 f->gltype = GL_UNSIGNED_SHORT_1_5_5_5_REV;
273 f->glintformat = GL_RGBA;
275 if (amsbBit == 0 && bgrBit == 0) {
276 f->glformat = GL_RGBA;
277 f->gltype = GL_UNSIGNED_SHORT_4_4_4_4;
279 }else if (amsbBit == 1 && bgrBit == 0) {
280 f->glformat = GL_BGRA;
281 f->gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV;
283 }else if (amsbBit == 0 && bgrBit == 1) {
284 f->glformat = GL_BGRA;
285 f->gltype = GL_UNSIGNED_SHORT_4_4_4_4;
287 }else if (amsbBit == 1 && bgrBit == 1) {
288 f->glformat = GL_RGBA;
289 f->gltype = GL_UNSIGNED_SHORT_4_4_4_4_REV;
295 f->glintformat = GL_RGB;
298 f->glformat = GL_RGB;
299 f->gltype = GL_UNSIGNED_SHORT_5_6_5;
301 }else if (bgrBit == 1) {
302 f->glformat = GL_RGB;
303 f->gltype = GL_UNSIGNED_SHORT_5_6_5;
310 f->glintformat = GL_LUMINANCE;
311 f->glformat = GL_LUMINANCE;
312 f->gltype = GL_UNSIGNED_BYTE;
317 f->glintformat = GL_ALPHA;
318 f->glformat = GL_ALPHA;
319 f->gltype = GL_UNSIGNED_BYTE;
331 /*-----------------------------------------------------
332 * Returns 1 if the given format is valid according to
333 * the OpenVG specification, else 0.
334 *-----------------------------------------------------*/
336 int shIsValidImageFormat(VGImageFormat format)
338 SHint aOrderBit = (1 << 6);
339 SHint rgbOrderBit = (1 << 7);
340 SHint baseFormat = format & 0x1F;
341 SHint unorderedRgba = format & (~(aOrderBit | rgbOrderBit));
342 SHint isRgba = (baseFormat == VG_sRGBX_8888 ||
343 baseFormat == VG_sRGBA_8888 ||
344 baseFormat == VG_sRGBA_8888_PRE ||
345 baseFormat == VG_sRGBA_5551 ||
346 baseFormat == VG_sRGBA_4444 ||
347 baseFormat == VG_lRGBX_8888 ||
348 baseFormat == VG_lRGBA_8888 ||
349 baseFormat == VG_lRGBA_8888_PRE);
351 SHint check = isRgba ? unorderedRgba : format;
352 return check >= VG_sRGBX_8888 && check <= VG_BW_1;
355 /*-----------------------------------------------------
356 * Returns 1 if the given format is supported by this
358 *-----------------------------------------------------*/
360 int shIsSupportedImageFormat(VGImageFormat format)
362 SHuint32 baseFormat = (format & 0x1F);
363 if (baseFormat == VG_sRGBA_8888_PRE ||
364 baseFormat == VG_lRGBA_8888_PRE ||
365 baseFormat == VG_BW_1)
371 /*--------------------------------------------------------
372 * Packs the pixel color components into memory at given
373 * address according to given format
374 *--------------------------------------------------------*/
376 void shStoreColor(SHColor *c, void *data, SHImageFormatDesc *f)
379 TODO: unsupported formats:
380 - s and l both behave linearly
381 - 1-bit black & white (BW_1)
387 if (f->vgformat == VG_lL_8 || f->vgformat == VG_sL_8) {
389 /* Grayscale (luminosity) conversion as defined by the spec */
390 l = 0.2126f * c->r + 0.7152f * c->g + 0.0722f * c->r;
391 out = (SHuint32)(l * (SHfloat)f->rmax + 0.5f);
395 /* Pack color components */
396 out += ( ((SHuint32)(c->r * (SHfloat)f->rmax + 0.5f)) << f->rshift ) & f->rmask;
397 out += ( ((SHuint32)(c->g * (SHfloat)f->gmax + 0.5f)) << f->gshift ) & f->gmask;
398 out += ( ((SHuint32)(c->b * (SHfloat)f->bmax + 0.5f)) << f->bshift ) & f->bmask;
399 out += ( ((SHuint32)(c->a * (SHfloat)f->amax + 0.5f)) << f->ashift ) & f->amask;
402 /* Store to buffer */
404 case 4: *((SHuint32*)data) = (SHuint32)(out & 0xFFFFFFFF); break;
405 case 2: *((SHuint16*)data) = (SHuint16)(out & 0x0000FFFF); break;
406 case 1: *((SHuint8*)data) = (SHuint8) (out & 0x000000FF); break;
410 /*---------------------------------------------------------
411 * Unpacks the pixel color components from memory at given
412 * address according to the given format
413 *---------------------------------------------------------*/
415 void shLoadColor(SHColor *c, const void *data, SHImageFormatDesc *f)
418 TODO: unsupported formats:
419 - s and l both behave linearly
420 - 1-bit black & white (BW_1)
425 /* Load from buffer */
427 case 4: in = (SHuint32) *((SHuint32*)data); break;
428 case 2: in = (SHuint32) *((SHuint16*)data); break;
429 case 1: in = (SHuint32) *((SHuint8*)data); break;
432 /* Unpack color components */
433 c->r = (SHfloat)((in & f->rmask) >> f->rshift) / (SHfloat) f->rmax;
434 c->g = (SHfloat)((in & f->gmask) >> f->gshift) / (SHfloat) f->gmax;
435 c->b = (SHfloat)((in & f->bmask) >> f->bshift) / (SHfloat) f->bmax;
436 c->a = (SHfloat)((in & f->amask) >> f->ashift) / (SHfloat) f->amax;
438 /* Initialize unused components to 1 */
439 if (f->amask == 0x0) { c->a = 1.0f; }
440 if (f->rmask == 0x0) { c->r = 1.0f; c->g = 1.0f; c->b = 1.0f; }
444 /*----------------------------------------------
445 * Color and Image constructors and destructors
446 *----------------------------------------------*/
448 void SHColor_ctor(SHColor *c)
456 void SHColor_dtor(SHColor *c) {
459 void SHImage_ctor(SHImage *i)
464 glGenTextures(1, &i->texture);
467 void SHImage_dtor(SHImage *i)
472 if (glIsTexture(i->texture))
473 glDeleteTextures(1, &i->texture);
476 /*--------------------------------------------------------
477 * Finds appropriate OpenGL texture size for the size of
479 *--------------------------------------------------------*/
481 void shUpdateImageTextureSize(SHImage *i)
483 i->texwidth = i->width;
484 i->texheight = i->height;
486 i->texheightK = 1.0f;
488 /* Round size to nearest power of 2 */
489 /* TODO: might be dropped out if it works without */
492 while (i->texwidth < i->width)
496 while (i->texheight < i->height)
499 i->texwidthK = (SHfloat)i->width / i->texwidth;
500 i->texheightK = (SHfloat)i->height / i->texheight; */
503 /*--------------------------------------------------
504 * Downloads the image data from OpenVG into
506 *--------------------------------------------------*/
508 void shUpdateImageTexture(SHImage *i, VGContext *c)
514 /* Find nearest power of two size */
517 while (potwidth < i->width)
521 while (potheight < i->height)
525 /* Scale into a temp buffer if image not a power-of-two size (pot)
526 and non-power-of-two textures are not supported by OpenGL */
528 if ((i->width < potwidth || i->height < potheight) &&
529 !c->isGLAvailable_TextureNonPowerOfTwo) {
531 potdata = (SHint8*)malloc( potwidth * potheight * i->fd.bytes );
532 if (!potdata) return;
534 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
535 glPixelStorei(GL_PACK_ALIGNMENT, 1);
536 glBindTexture(GL_TEXTURE_2D, i->texture);
539 gluScaleImage(i->fd.glformat, i->width, i->height, i->fd.gltype, i->data,
540 potwidth, potheight, i->fd.gltype, potdata);
542 glTexImage2D(GL_TEXTURE_2D, 0, i->fd.glintformat, potwidth, potheight, 0,
543 i->fd.glformat, i->fd.gltype, potdata);
549 /* Store pixels to texture */
550 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
551 glBindTexture(GL_TEXTURE_2D, i->texture);
552 glTexImage2D(GL_TEXTURE_2D, 0, i->fd.glintformat,
553 i->texwidth, i->texheight, 0,
554 i->fd.glformat, i->fd.gltype, i->data);
557 /*----------------------------------------------------------
558 * Creates a new image object and returns the handle to it
559 *----------------------------------------------------------*/
561 VG_API_CALL VGImage vgCreateImage(VGImageFormat format,
562 VGint width, VGint height,
563 VGbitfield allowedQuality)
566 SHImageFormatDesc fd;
567 VG_GETCONTEXT(VG_INVALID_HANDLE);
569 /* Reject invalid formats */
570 VG_RETURN_ERR_IF(!shIsValidImageFormat(format),
571 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
574 /* Reject unsupported formats */
575 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(format),
576 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
579 /* Reject invalid sizes */
580 VG_RETURN_ERR_IF(width <= 0 || width > SH_MAX_IMAGE_WIDTH ||
581 height <= 0 || height > SH_MAX_IMAGE_HEIGHT ||
582 width * height > SH_MAX_IMAGE_PIXELS,
583 VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
585 /* Check if byte size exceeds SH_MAX_IMAGE_BYTES */
586 shSetupImageFormat(format, &fd);
587 VG_RETURN_ERR_IF(width * height * fd.bytes > SH_MAX_IMAGE_BYTES,
588 VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
590 /* Reject invalid quality bits */
591 VG_RETURN_ERR_IF(allowedQuality &
592 ~(VG_IMAGE_QUALITY_NONANTIALIASED |
593 VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER),
594 VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
596 /* Create new image object */
597 SH_NEWOBJ(SHImage, i);
598 VG_RETURN_ERR_IF(!i, VG_OUT_OF_MEMORY_ERROR, VG_INVALID_HANDLE);
603 /* Allocate data memory */
604 shUpdateImageTextureSize(i);
605 i->data = (SHuint8*)malloc( i->texwidth * i->texheight * fd.bytes );
607 if (i->data == NULL) {
608 SH_DELETEOBJ(SHImage, i);
609 VG_RETURN_ERR(VG_OUT_OF_MEMORY_ERROR, VG_INVALID_HANDLE); }
611 /* Initialize data by zeroing-out */
612 memset(i->data, 1, width * height * fd.bytes);
613 shUpdateImageTexture(i, context);
615 /* Add to resource list */
616 shImageArrayPushBack(&context->images, i);
618 VG_RETURN((VGImage)i);
621 VG_API_CALL void vgDestroyImage(VGImage image)
624 VG_GETCONTEXT(VG_NO_RETVAL);
626 /* Check if valid resource */
627 index = shImageArrayFind(&context->images, (SHImage*)image);
628 VG_RETURN_ERR_IF(index == -1, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
630 /* Delete object and remove resource */
631 SH_DELETEOBJ(SHImage, (SHImage*)image);
632 shImageArrayRemoveAt(&context->images, index);
634 VG_RETURN(VG_NO_RETVAL);
637 /*---------------------------------------------------
638 * Clear given rectangle area in the image data with
639 * color set via vgSetfv(VG_CLEAR_COLOR, ...)
640 *---------------------------------------------------*/
642 VG_API_CALL void vgClearImage(VGImage image,
643 VGint x, VGint y, VGint width, VGint height)
648 SHint X,Y, ix, iy, dx, dy, stride;
649 VG_GETCONTEXT(VG_NO_RETVAL);
651 VG_RETURN_ERR_IF(!shIsValidImage(context, image),
652 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
654 /* TODO: check if image current render target */
657 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
658 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
660 /* Nothing to do if target rectangle out of bounds */
661 if (x >= i->width || y >= i->height)
662 VG_RETURN(VG_NO_RETVAL);
663 if (x + width < 0 || y + height < 0)
664 VG_RETURN(VG_NO_RETVAL);
666 /* Clamp to image bounds */
667 ix = SH_MAX(x, 0); dx = ix - x;
668 iy = SH_MAX(y, 0); dy = iy - y;
669 width = SH_MIN( width - dx, i->width - ix);
670 height = SH_MIN( height - dy, i->height - iy);
671 stride = i->texwidth * i->fd.bytes;
673 /* Walk pixels and clear*/
674 clear = context->clearColor;
676 for (Y=iy; Y<iy+height; ++Y) {
677 data = i->data + ( Y*stride + ix * i->fd.bytes );
679 for (X=ix; X<ix+width; ++X) {
680 shStoreColor(&clear, data, &i->fd);
684 shUpdateImageTexture(i, context);
685 VG_RETURN(VG_NO_RETVAL);
688 /*------------------------------------------------------------
689 * Generic function for copying a rectangle area of pixels
690 * of size (width,height) among two data buffers. The size of
691 * source (swidth,sheight) and destination (dwidth,dheight)
692 * images may vary as well as the source coordinates (sx,sy)
693 * and destination coordinates(dx, dy).
694 *------------------------------------------------------------*/
696 void shCopyPixels(SHuint8 *dst, VGImageFormat dstFormat, SHint dstStride,
697 const SHuint8 *src, VGImageFormat srcFormat, SHint srcStride,
698 SHint dwidth, SHint dheight, SHint swidth, SHint sheight,
699 SHint dx, SHint dy, SHint sx, SHint sy,
700 SHint width, SHint height)
703 SHint SX, SY, DX, DY;
708 SHImageFormatDesc dfd;
709 SHImageFormatDesc sfd;
711 /* Setup image format descriptors */
712 SH_ASSERT(shIsSupportedImageFormat(dstFormat));
713 SH_ASSERT(shIsSupportedImageFormat(srcFormat));
714 shSetupImageFormat(dstFormat, &dfd);
715 shSetupImageFormat(srcFormat, &sfd);
718 In order to optimize the copying loop and remove the
719 if statements from it to check whether target pixel
720 is in the source and destination surface, we clamp
721 copy rectangle in advance. This is quite a tedious
722 task though. Here is a picture of the scene. Note that
723 (dx,dy) is actually an offset of the copy rectangle
724 (clamped to src surface) from the (0,0) point on dst
725 surface. A negative (dx,dy) (as in this picture) also
726 affects src coords of the copy rectangle which have
727 to be readjusted again (sx,sy,width,height).
730 *----------------------*
731 | (sx,sy) copy rect |
734 | | *------------------------------*
738 | | (width,height) | |
739 *----------------------* |
741 *------------------------------*
745 /* Cancel if copy rect out of src bounds */
746 if (sx >= swidth || sy >= sheight) return;
747 if (sx + width < 0 || sy + height < 0) return;
749 /* Clamp copy rectangle to src bounds */
752 width = SH_MIN(width, swidth - sx);
753 height = SH_MIN(height, sheight - sy);
755 /* Cancel if copy rect out of dst bounds */
756 if (dx >= dwidth || dy >= dheight) return;
757 if (dx + width < 0 || dy + height < 0) return;
759 /* Clamp copy rectangle to dst bounds */
760 dxold = dx; dyold = dy;
766 height -= dy - dyold;
767 width = SH_MIN(width, dwidth - dx);
768 height = SH_MIN(height, dheight - dy);
770 /* Calculate stride from format if not given */
771 if (dstStride == -1) dstStride = dwidth * dfd.bytes;
772 if (srcStride == -1) srcStride = swidth * sfd.bytes;
774 if (srcFormat == dstFormat) {
776 /* Walk pixels and copy */
777 for (SY=sy, DY=dy; SY < sy+height; ++SY, ++DY) {
778 SD = src + SY * srcStride + sx * sfd.bytes;
779 DD = dst + DY * dstStride + dx * dfd.bytes;
780 memcpy(DD, SD, width * sfd.bytes);
785 /* Walk pixels and copy */
786 for (SY=sy, DY=dy; SY < sy+height; ++SY, ++DY) {
787 SD = src + SY * srcStride + sx * sfd.bytes;
788 DD = dst + DY * dstStride + dx * dfd.bytes;
790 for (SX=sx, DX=dx; SX < sx+width; ++SX, ++DX) {
791 shLoadColor(&c, SD, &sfd);
792 shStoreColor(&c, DD, &dfd);
793 SD += sfd.bytes; DD += dfd.bytes;
798 /*---------------------------------------------------------
799 * Copies a rectangle area of pixels of size (width,height)
800 * from given data buffer to image surface at destination
802 *---------------------------------------------------------*/
804 VG_API_CALL void vgImageSubData(VGImage image,
805 const void * data, VGint dataStride,
806 VGImageFormat dataFormat,
807 VGint x, VGint y, VGint width, VGint height)
810 VG_GETCONTEXT(VG_NO_RETVAL);
812 VG_RETURN_ERR_IF(!shIsValidImage(context, image),
813 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
815 /* TODO: check if image current render target */
818 /* Reject invalid formats */
819 VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
820 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
823 /* Reject unsupported image formats */
824 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
825 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
828 VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
829 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
831 /* TODO: check data array alignment */
833 shCopyPixels(i->data, i->fd.vgformat, i->texwidth * i->fd.bytes,
834 data, dataFormat,dataStride,
835 i->width, i->height, width, height,
836 x, y, 0, 0, width, height);
838 shUpdateImageTexture(i, context);
839 VG_RETURN(VG_NO_RETVAL);
842 /*---------------------------------------------------------
843 * Copies a rectangle area of pixels of size (width,height)
844 * from image surface at source coordinates (x,y) to given
846 *---------------------------------------------------------*/
848 VG_API_CALL void vgGetImageSubData(VGImage image,
849 void * data, VGint dataStride,
850 VGImageFormat dataFormat,
852 VGint width, VGint height)
855 VG_GETCONTEXT(VG_NO_RETVAL);
857 VG_RETURN_ERR_IF(!shIsValidImage(context, image),
858 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
860 /* TODO: check if image current render target */
863 /* Reject invalid formats */
864 VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
865 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
868 /* Reject unsupported formats */
869 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
870 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
873 VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
874 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
876 /* TODO: check data array alignment */
878 shCopyPixels(data, dataFormat, dataStride,
879 i->data, i->fd.vgformat, i->texwidth * i->fd.bytes,
880 width, height, i->width, i->height,
881 0,0,x,x,width,height);
883 VG_RETURN(VG_NO_RETVAL);
886 /*----------------------------------------------------------
887 * Copies a rectangle area of pixels of size (width,height)
888 * from src image surface at source coordinates (sx,sy) to
889 * dst image surface at destination cordinates (dx,dy)
890 *---------------------------------------------------------*/
892 VG_API_CALL void vgCopyImage(VGImage dst, VGint dx, VGint dy,
893 VGImage src, VGint sx, VGint sy,
894 VGint width, VGint height,
900 VG_GETCONTEXT(VG_NO_RETVAL);
902 VG_RETURN_ERR_IF(!shIsValidImage(context, src) ||
903 !shIsValidImage(context, dst),
904 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
906 /* TODO: check if images current render target */
908 s = (SHImage*)src; d = (SHImage*)dst;
909 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
910 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
912 /* In order to perform copying in a cosistent fashion
913 we first copy to a temporary buffer and only then to
916 /* TODO: rather check first if the image is really
917 the same and whether the regions overlap. if not
918 we can copy directly */
920 pixels = (SHuint8*)malloc(width * height * s->fd.bytes);
921 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
923 shCopyPixels(pixels, s->fd.vgformat, s->texwidth * s->fd.bytes,
924 s->data, s->fd.vgformat, s->texwidth * s->fd.bytes,
925 width, height, s->width, s->height,
926 0, 0, sx, sy, width, height);
928 shCopyPixels(d->data, d->fd.vgformat, d->texwidth * d->fd.bytes,
929 pixels, s->fd.vgformat, s->texwidth * s->fd.bytes,
930 d->width, d->height, width, height,
931 dx, dy, 0, 0, width, height);
935 shUpdateImageTexture(d, context);
936 VG_RETURN(VG_NO_RETVAL);
939 /*---------------------------------------------------------
940 * Copies a rectangle area of pixels of size (width,height)
941 * from src image surface at source coordinates (sx,sy) to
942 * window surface at destination coordinates (dx,dy)
943 *---------------------------------------------------------*/
945 VG_API_CALL void vgSetPixels(VGint dx, VGint dy,
946 VGImage src, VGint sx, VGint sy,
947 VGint width, VGint height)
951 SHImageFormatDesc winfd;
953 VG_GETCONTEXT(VG_NO_RETVAL);
955 VG_RETURN_ERR_IF(!shIsValidImage(context, src),
956 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
958 /* TODO: check if image current render target (requires EGL) */
961 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
962 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
964 /* Setup window image format descriptor */
965 /* TODO: this actually depends on the target framebuffer type
966 if we really want the copy to be optimized */
967 shSetupImageFormat(VG_sRGBA_8888, &winfd);
969 /* OpenGL doesn't allow us to use random stride. We have to
970 manually copy the image data and write from a copy with
971 normal row length (without power-of-two roundup pixels) */
973 pixels = (SHuint8*)malloc(width * height * winfd.bytes);
974 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
976 shCopyPixels(pixels, winfd.vgformat, -1,
977 i->data, i->fd.vgformat, i->texwidth * i->fd.bytes,
978 width, height, i->width, i->height,
979 0,0,sx,sy, width, height);
981 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
982 glRasterPos2i(dx, dy);
983 glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
988 VG_RETURN(VG_NO_RETVAL);
991 /*---------------------------------------------------------
992 * Copies a rectangle area of pixels of size (width,height)
993 * from given data buffer at source coordinates (sx,sy) to
994 * window surface at destination coordinates (dx,dy)
995 *---------------------------------------------------------*/
997 VG_API_CALL void vgWritePixels(const void * data, VGint dataStride,
998 VGImageFormat dataFormat,
1000 VGint width, VGint height)
1003 SHImageFormatDesc winfd;
1005 VG_GETCONTEXT(VG_NO_RETVAL);
1007 /* Reject invalid formats */
1008 VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
1009 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1012 /* Reject unsupported formats */
1013 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
1014 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1017 /* TODO: check output data array alignment */
1019 VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
1020 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
1022 /* Setup window image format descriptor */
1023 /* TODO: this actually depends on the target framebuffer type
1024 if we really want the copy to be optimized */
1025 shSetupImageFormat(VG_sRGBA_8888, &winfd);
1027 /* OpenGL doesn't allow us to use random stride. We have to
1028 manually copy the image data and write from a copy with
1029 normal row length */
1031 pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1032 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1034 shCopyPixels(pixels, winfd.vgformat, -1,
1035 (SHuint8*)data, dataFormat, dataStride,
1036 width, height, width, height,
1037 0,0,0,0, width, height);
1039 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1040 glRasterPos2i(dx, dy);
1041 glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1046 VG_RETURN(VG_NO_RETVAL);
1049 /*-----------------------------------------------------------
1050 * Copies a rectangle area of pixels of size (width, height)
1051 * from window surface at source coordinates (sx, sy) to
1052 * image surface at destination coordinates (dx, dy)
1053 *-----------------------------------------------------------*/
1055 VG_API_CALL void vgGetPixels(VGImage dst, VGint dx, VGint dy,
1057 VGint width, VGint height)
1061 SHImageFormatDesc winfd;
1062 VG_GETCONTEXT(VG_NO_RETVAL);
1064 VG_RETURN_ERR_IF(!shIsValidImage(context, dst),
1065 VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1067 /* TODO: check if image current render target */
1070 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
1071 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
1073 /* Setup window image format descriptor */
1074 /* TODO: this actually depends on the target framebuffer type
1075 if we really want the copy to be optimized */
1076 shSetupImageFormat(VG_sRGBA_8888, &winfd);
1078 /* OpenGL doesn't allow us to read to random destination
1079 coordinates nor using random stride. We have to
1080 read first and then manually copy to the image data */
1082 pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1083 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1085 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1086 glReadPixels(sx, sy, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1088 shCopyPixels(i->data, i->fd.vgformat, i->texwidth * i->fd.bytes,
1089 pixels, winfd.vgformat, -1,
1090 i->width, i->height, width, height,
1091 dx, dy, 0, 0, width, height);
1095 shUpdateImageTexture(i, context);
1096 VG_RETURN(VG_NO_RETVAL);
1099 /*-----------------------------------------------------------
1100 * Copies a rectangle area of pixels of size (width, height)
1101 * from window surface at source coordinates (sx, sy) to
1102 * to given output data buffer.
1103 *-----------------------------------------------------------*/
1105 VG_API_CALL void vgReadPixels(void * data, VGint dataStride,
1106 VGImageFormat dataFormat,
1108 VGint width, VGint height)
1111 SHImageFormatDesc winfd;
1112 VG_GETCONTEXT(VG_NO_RETVAL);
1114 /* Reject invalid formats */
1115 VG_RETURN_ERR_IF(!shIsValidImageFormat(dataFormat),
1116 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1119 /* Reject unsupported image formats */
1120 VG_RETURN_ERR_IF(!shIsSupportedImageFormat(dataFormat),
1121 VG_UNSUPPORTED_IMAGE_FORMAT_ERROR,
1124 /* TODO: check output data array alignment */
1126 VG_RETURN_ERR_IF(width <= 0 || height <= 0 || !data,
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 random data stride. We have to
1135 read first and then manually copy to the output buffer */
1137 pixels = (SHuint8*)malloc(width * height * winfd.bytes);
1138 SH_RETURN_ERR_IF(!pixels, VG_OUT_OF_MEMORY_ERROR, SH_NO_RETVAL);
1140 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1141 glReadPixels(sx, sy, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
1143 shCopyPixels(data, dataFormat, dataStride,
1144 pixels, winfd.vgformat, -1,
1145 width, height, width, height,
1146 0, 0, 0, 0, width, height);
1150 VG_RETURN(VG_NO_RETVAL);
1153 /*----------------------------------------------------------
1154 * Copies a rectangle area of pixels of size (width,height)
1155 * from window surface at source coordinates (sx,sy) to
1156 * windows surface at destination cordinates (dx,dy)
1157 *---------------------------------------------------------*/
1159 VG_API_CALL void vgCopyPixels(VGint dx, VGint dy,
1161 VGint width, VGint height)
1163 VG_GETCONTEXT(VG_NO_RETVAL);
1165 VG_RETURN_ERR_IF(width <= 0 || height <= 0,
1166 VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
1168 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1169 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1170 glRasterPos2i(dx, dy);
1171 glCopyPixels(sx, sy, width, height, GL_COLOR);
1172 glRasterPos2i(0, 0);
1174 VG_RETURN(VG_NO_RETVAL);
1177 VG_API_CALL VGImage vgChildImage(VGImage parent,
1178 VGint x, VGint y, VGint width, VGint height)
1180 return VG_INVALID_HANDLE;
1183 VG_API_CALL VGImage vgGetParent(VGImage image)
1185 return VG_INVALID_HANDLE;
1188 VG_API_CALL void vgColorMatrix(VGImage dst, VGImage src,
1189 const VGfloat * matrix)
1193 VG_API_CALL void vgConvolve(VGImage dst, VGImage src,
1194 VGint kernelWidth, VGint kernelHeight,
1195 VGint shiftX, VGint shiftY,
1196 const VGshort * kernel,
1199 VGTilingMode tilingMode)
1203 VG_API_CALL void vgSeparableConvolve(VGImage dst, VGImage src,
1206 VGint shiftX, VGint shiftY,
1207 const VGshort * kernelX,
1208 const VGshort * kernelY,
1211 VGTilingMode tilingMode)
1215 VG_API_CALL void vgGaussianBlur(VGImage dst, VGImage src,
1216 VGfloat stdDeviationX,
1217 VGfloat stdDeviationY,
1218 VGTilingMode tilingMode)
1222 VG_API_CALL void vgLookup(VGImage dst, VGImage src,
1223 const VGubyte * redLUT,
1224 const VGubyte * greenLUT,
1225 const VGubyte * blueLUT,
1226 const VGubyte * alphaLUT,
1227 VGboolean outputLinear,
1228 VGboolean outputPremultiplied)
1232 VG_API_CALL void vgLookupSingle(VGImage dst, VGImage src,
1233 const VGuint * lookupTable,
1234 VGImageChannel sourceChannel,
1235 VGboolean outputLinear,
1236 VGboolean outputPremultiplied)