api_images.c revision 96c6637a1360f146bbf49ffb207ae943ecbbdf49
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27#include "image.h" 28 29#include "VG/openvg.h" 30 31#include "vg_context.h" 32#include "vg_translate.h" 33#include "api_consts.h" 34#include "api.h" 35 36#include "pipe/p_context.h" 37#include "pipe/p_screen.h" 38#include "util/u_inlines.h" 39#include "util/u_tile.h" 40#include "util/u_math.h" 41 42static INLINE VGboolean supported_image_format(VGImageFormat format) 43{ 44 switch(format) { 45 case VG_sRGBX_8888: 46 case VG_sRGBA_8888: 47 case VG_sRGBA_8888_PRE: 48 case VG_sRGB_565: 49 case VG_sRGBA_5551: 50 case VG_sRGBA_4444: 51 case VG_sL_8: 52 case VG_lRGBX_8888: 53 case VG_lRGBA_8888: 54 case VG_lRGBA_8888_PRE: 55 case VG_lL_8: 56 case VG_A_8: 57 case VG_BW_1: 58#ifdef OPENVG_VERSION_1_1 59 case VG_A_1: 60 case VG_A_4: 61#endif 62 case VG_sXRGB_8888: 63 case VG_sARGB_8888: 64 case VG_sARGB_8888_PRE: 65 case VG_sARGB_1555: 66 case VG_sARGB_4444: 67 case VG_lXRGB_8888: 68 case VG_lARGB_8888: 69 case VG_lARGB_8888_PRE: 70 case VG_sBGRX_8888: 71 case VG_sBGRA_8888: 72 case VG_sBGRA_8888_PRE: 73 case VG_sBGR_565: 74 case VG_sBGRA_5551: 75 case VG_sBGRA_4444: 76 case VG_lBGRX_8888: 77 case VG_lBGRA_8888: 78 case VG_lBGRA_8888_PRE: 79 case VG_sXBGR_8888: 80 case VG_sABGR_8888: 81 case VG_sABGR_8888_PRE: 82 case VG_sABGR_1555: 83 case VG_sABGR_4444: 84 case VG_lXBGR_8888: 85 case VG_lABGR_8888: 86 case VG_lABGR_8888_PRE: 87 return VG_TRUE; 88 default: 89 return VG_FALSE; 90 } 91 return VG_FALSE; 92} 93 94VGImage vegaCreateImage(VGImageFormat format, 95 VGint width, VGint height, 96 VGbitfield allowedQuality) 97{ 98 struct vg_context *ctx = vg_current_context(); 99 100 if (!supported_image_format(format)) { 101 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 102 return VG_INVALID_HANDLE; 103 } 104 if (width <= 0 || height <= 0) { 105 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 106 return VG_INVALID_HANDLE; 107 } 108 if (width > vgGeti(VG_MAX_IMAGE_WIDTH) || 109 height > vgGeti(VG_MAX_IMAGE_HEIGHT)) { 110 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 111 return VG_INVALID_HANDLE; 112 } 113 if (width * height > vgGeti(VG_MAX_IMAGE_PIXELS)) { 114 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 115 return VG_INVALID_HANDLE; 116 } 117 118 if (!(allowedQuality & ((VG_IMAGE_QUALITY_NONANTIALIASED | 119 VG_IMAGE_QUALITY_FASTER | 120 VG_IMAGE_QUALITY_BETTER)))) { 121 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 122 return VG_INVALID_HANDLE; 123 } 124 125 return (VGImage)image_create(format, width, height); 126} 127 128void vegaDestroyImage(VGImage image) 129{ 130 struct vg_context *ctx = vg_current_context(); 131 struct vg_image *img = (struct vg_image *)image; 132 133 if (image == VG_INVALID_HANDLE) { 134 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 135 return; 136 } 137 if (!vg_object_is_valid((void*)image, VG_OBJECT_IMAGE)) { 138 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 139 return; 140 } 141 image_destroy(img); 142} 143 144void vegaClearImage(VGImage image, 145 VGint x, VGint y, 146 VGint width, VGint height) 147{ 148 struct vg_context *ctx = vg_current_context(); 149 struct vg_image *img; 150 151 if (image == VG_INVALID_HANDLE) { 152 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 153 return; 154 } 155 if (width <= 0 || height <= 0) { 156 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 157 return; 158 } 159 160 img = (struct vg_image*)image; 161 162 if (x + width < 0 || y + height < 0) 163 return; 164 165 image_clear(img, x, y, width, height); 166 167} 168 169void vegaImageSubData(VGImage image, 170 const void * data, 171 VGint dataStride, 172 VGImageFormat dataFormat, 173 VGint x, VGint y, 174 VGint width, VGint height) 175{ 176 struct vg_context *ctx = vg_current_context(); 177 struct vg_image *img; 178 179 if (image == VG_INVALID_HANDLE) { 180 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 181 return; 182 } 183 if (!supported_image_format(dataFormat)) { 184 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 185 return; 186 } 187 if (width <= 0 || height <= 0 || !data || !is_aligned(data)) { 188 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 189 return; 190 } 191 192 img = (struct vg_image*)(image); 193 image_sub_data(img, data, dataStride, dataFormat, 194 x, y, width, height); 195} 196 197void vegaGetImageSubData(VGImage image, 198 void * data, 199 VGint dataStride, 200 VGImageFormat dataFormat, 201 VGint x, VGint y, 202 VGint width, VGint height) 203{ 204 struct vg_context *ctx = vg_current_context(); 205 struct vg_image *img; 206 207 if (image == VG_INVALID_HANDLE) { 208 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 209 return; 210 } 211 if (!supported_image_format(dataFormat)) { 212 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 213 return; 214 } 215 if (width <= 0 || height <= 0 || !data || !is_aligned(data)) { 216 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 217 return; 218 } 219 img = (struct vg_image*)image; 220 image_get_sub_data(img, data, dataStride, dataFormat, 221 x, y, width, height); 222} 223 224VGImage vegaChildImage(VGImage parent, 225 VGint x, VGint y, 226 VGint width, VGint height) 227{ 228 struct vg_context *ctx = vg_current_context(); 229 struct vg_image *p; 230 231 if (parent == VG_INVALID_HANDLE || 232 !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void*)parent) || 233 !vg_object_is_valid((void*)parent, VG_OBJECT_IMAGE)) { 234 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 235 return VG_INVALID_HANDLE; 236 } 237 if (width <= 0 || height <= 0 || x < 0 || y < 0) { 238 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 239 return VG_INVALID_HANDLE; 240 } 241 p = (struct vg_image *)parent; 242 if (x > p->width || y > p->height) { 243 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 244 return VG_INVALID_HANDLE; 245 } 246 if (x + width > p->width || y + height > p->height) { 247 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 248 return VG_INVALID_HANDLE; 249 } 250 251 return (VGImage)image_child_image(p, x, y, width, height); 252} 253 254VGImage vegaGetParent(VGImage image) 255{ 256 struct vg_context *ctx = vg_current_context(); 257 struct vg_image *img; 258 259 if (image == VG_INVALID_HANDLE) { 260 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 261 return VG_INVALID_HANDLE; 262 } 263 264 img = (struct vg_image*)image; 265 if (img->parent) 266 return (VGImage)img->parent; 267 else 268 return image; 269} 270 271void vegaCopyImage(VGImage dst, VGint dx, VGint dy, 272 VGImage src, VGint sx, VGint sy, 273 VGint width, VGint height, 274 VGboolean dither) 275{ 276 struct vg_context *ctx = vg_current_context(); 277 278 if (src == VG_INVALID_HANDLE || dst == VG_INVALID_HANDLE) { 279 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 280 return; 281 } 282 283 if (width <= 0 || height <= 0) { 284 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 285 return; 286 } 287 vg_validate_state(ctx); 288 image_copy((struct vg_image*)dst, dx, dy, 289 (struct vg_image*)src, sx, sy, 290 width, height, dither); 291} 292 293void vegaDrawImage(VGImage image) 294{ 295 struct vg_context *ctx = vg_current_context(); 296 297 if (!ctx) 298 return; 299 300 if (image == VG_INVALID_HANDLE) { 301 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 302 return; 303 } 304 305 vg_validate_state(ctx); 306 image_draw((struct vg_image*)image); 307} 308 309void vegaSetPixels(VGint dx, VGint dy, 310 VGImage src, VGint sx, VGint sy, 311 VGint width, VGint height) 312{ 313 struct vg_context *ctx = vg_current_context(); 314 315 vg_validate_state(ctx); 316 317 if (src == VG_INVALID_HANDLE) { 318 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 319 return; 320 } 321 if (width <= 0 || height <= 0) { 322 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 323 return; 324 } 325 image_set_pixels(dx, dy, (struct vg_image*)src, sx, sy, width, 326 height); 327} 328 329void vegaGetPixels(VGImage dst, VGint dx, VGint dy, 330 VGint sx, VGint sy, 331 VGint width, VGint height) 332{ 333 struct vg_context *ctx = vg_current_context(); 334 struct vg_image *img; 335 336 if (dst == VG_INVALID_HANDLE) { 337 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 338 return; 339 } 340 if (width <= 0 || height <= 0) { 341 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 342 return; 343 } 344 345 img = (struct vg_image*)dst; 346 347 image_get_pixels(img, dx, dy, 348 sx, sy, width, height); 349} 350 351void vegaWritePixels(const void * data, VGint dataStride, 352 VGImageFormat dataFormat, 353 VGint dx, VGint dy, 354 VGint width, VGint height) 355{ 356 struct vg_context *ctx = vg_current_context(); 357 struct pipe_context *pipe = ctx->pipe; 358 359 if (!supported_image_format(dataFormat)) { 360 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 361 return; 362 } 363 if (!data || !is_aligned(data)) { 364 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 365 return; 366 } 367 if (width <= 0 || height <= 0) { 368 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 369 return; 370 } 371 372 vg_validate_state(ctx); 373 { 374 struct vg_image *img = image_create(dataFormat, width, height); 375 image_sub_data(img, data, dataStride, dataFormat, 0, 0, 376 width, height); 377#if 0 378 struct matrix *matrix = &ctx->state.vg.image_user_to_surface_matrix; 379 matrix_translate(matrix, dx, dy); 380 image_draw(img); 381 matrix_translate(matrix, -dx, -dy); 382#else 383 /* this looks like a better approach */ 384 image_set_pixels(dx, dy, img, 0, 0, width, height); 385#endif 386 image_destroy(img); 387 } 388 /* make sure rendering has completed */ 389 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 390} 391 392void vegaReadPixels(void * data, VGint dataStride, 393 VGImageFormat dataFormat, 394 VGint sx, VGint sy, 395 VGint width, VGint height) 396{ 397 struct vg_context *ctx = vg_current_context(); 398 struct pipe_context *pipe = ctx->pipe; 399 400 struct st_framebuffer *stfb = ctx->draw_buffer; 401 struct st_renderbuffer *strb = stfb->strb; 402 403 VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; 404 VGfloat *df = (VGfloat*)temp; 405 VGint i; 406 VGubyte *dst = (VGubyte *)data; 407 VGint xoffset = 0, yoffset = 0; 408 409 if (!supported_image_format(dataFormat)) { 410 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 411 return; 412 } 413 if (!data || !is_aligned(data)) { 414 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 415 return; 416 } 417 if (width <= 0 || height <= 0) { 418 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 419 return; 420 } 421 422 /* make sure rendering has completed */ 423 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 424 if (sx < 0) { 425 xoffset = -sx; 426 xoffset *= _vega_size_for_format(dataFormat); 427 width += sx; 428 sx = 0; 429 } 430 if (sy < 0) { 431 yoffset = -sy; 432 yoffset *= dataStride; 433 height += sy; 434 sy = 0; 435 } 436 437 if (sx + width > stfb->width || sy + height > stfb->height) { 438 width = stfb->width - sx; 439 height = stfb->height - sy; 440 /* nothing to read */ 441 if (width <= 0 || height <= 0) 442 return; 443 } 444 445 { 446 VGint y = (stfb->height - sy) - 1, yStep = -1; 447 struct pipe_transfer *transfer; 448 449 transfer = pipe_get_transfer(pipe, strb->texture, 0, 0, 0, 450 PIPE_TRANSFER_READ, 451 0, 0, sx + width, stfb->height - sy); 452 453 /* Do a row at a time to flip image data vertically */ 454 for (i = 0; i < height; i++) { 455#if 0 456 debug_printf("%d-%d == %d\n", sy, height, y); 457#endif 458 pipe_get_tile_rgba(pipe, transfer, sx, y, width, 1, df); 459 y += yStep; 460 _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, 461 dst + yoffset + xoffset); 462 dst += dataStride; 463 } 464 465 pipe->transfer_destroy(pipe, transfer); 466 } 467} 468 469void vegaCopyPixels(VGint dx, VGint dy, 470 VGint sx, VGint sy, 471 VGint width, VGint height) 472{ 473 struct vg_context *ctx = vg_current_context(); 474 struct st_framebuffer *stfb = ctx->draw_buffer; 475 struct st_renderbuffer *strb = stfb->strb; 476 477 if (width <= 0 || height <= 0) { 478 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 479 return; 480 } 481 482 /* do nothing if we copy from outside the fb */ 483 if (dx >= (VGint)stfb->width || dy >= (VGint)stfb->height || 484 sx >= (VGint)stfb->width || sy >= (VGint)stfb->height) 485 return; 486 487 vg_validate_state(ctx); 488 /* make sure rendering has completed */ 489 vgFinish(); 490 491 vg_copy_surface(ctx, strb->surface, dx, dy, 492 strb->surface, sx, sy, width, height); 493} 494