api_images.c revision 4c7001462607e6e99e474d6271dd481d3f8f201c
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 &ctx->state.vg.image_user_to_surface_matrix); 308} 309 310void vegaSetPixels(VGint dx, VGint dy, 311 VGImage src, VGint sx, VGint sy, 312 VGint width, VGint height) 313{ 314 struct vg_context *ctx = vg_current_context(); 315 316 vg_validate_state(ctx); 317 318 if (src == VG_INVALID_HANDLE) { 319 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 320 return; 321 } 322 if (width <= 0 || height <= 0) { 323 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 324 return; 325 } 326 image_set_pixels(dx, dy, (struct vg_image*)src, sx, sy, width, 327 height); 328} 329 330void vegaGetPixels(VGImage dst, VGint dx, VGint dy, 331 VGint sx, VGint sy, 332 VGint width, VGint height) 333{ 334 struct vg_context *ctx = vg_current_context(); 335 struct vg_image *img; 336 337 if (dst == VG_INVALID_HANDLE) { 338 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 339 return; 340 } 341 if (width <= 0 || height <= 0) { 342 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 343 return; 344 } 345 346 img = (struct vg_image*)dst; 347 348 image_get_pixels(img, dx, dy, 349 sx, sy, width, height); 350} 351 352void vegaWritePixels(const void * data, VGint dataStride, 353 VGImageFormat dataFormat, 354 VGint dx, VGint dy, 355 VGint width, VGint height) 356{ 357 struct vg_context *ctx = vg_current_context(); 358 struct pipe_context *pipe = ctx->pipe; 359 360 if (!supported_image_format(dataFormat)) { 361 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 362 return; 363 } 364 if (!data || !is_aligned(data)) { 365 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 366 return; 367 } 368 if (width <= 0 || height <= 0) { 369 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 370 return; 371 } 372 373 vg_validate_state(ctx); 374 { 375 struct vg_image *img = image_create(dataFormat, width, height); 376 image_sub_data(img, data, dataStride, dataFormat, 0, 0, 377 width, height); 378#if 0 379 struct matrix *matrix = &ctx->state.vg.image_user_to_surface_matrix; 380 matrix_translate(matrix, dx, dy); 381 image_draw(img); 382 matrix_translate(matrix, -dx, -dy); 383#else 384 /* this looks like a better approach */ 385 image_set_pixels(dx, dy, img, 0, 0, width, height); 386#endif 387 image_destroy(img); 388 } 389 /* make sure rendering has completed */ 390 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 391} 392 393void vegaReadPixels(void * data, VGint dataStride, 394 VGImageFormat dataFormat, 395 VGint sx, VGint sy, 396 VGint width, VGint height) 397{ 398 struct vg_context *ctx = vg_current_context(); 399 struct pipe_context *pipe = ctx->pipe; 400 401 struct st_framebuffer *stfb = ctx->draw_buffer; 402 struct st_renderbuffer *strb = stfb->strb; 403 404 VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; 405 VGfloat *df = (VGfloat*)temp; 406 VGint i; 407 VGubyte *dst = (VGubyte *)data; 408 VGint xoffset = 0, yoffset = 0; 409 410 if (!supported_image_format(dataFormat)) { 411 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 412 return; 413 } 414 if (!data || !is_aligned(data)) { 415 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 416 return; 417 } 418 if (width <= 0 || height <= 0) { 419 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 420 return; 421 } 422 423 /* make sure rendering has completed */ 424 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 425 if (sx < 0) { 426 xoffset = -sx; 427 xoffset *= _vega_size_for_format(dataFormat); 428 width += sx; 429 sx = 0; 430 } 431 if (sy < 0) { 432 yoffset = -sy; 433 yoffset *= dataStride; 434 height += sy; 435 sy = 0; 436 } 437 438 if (sx + width > stfb->width || sy + height > stfb->height) { 439 width = stfb->width - sx; 440 height = stfb->height - sy; 441 /* nothing to read */ 442 if (width <= 0 || height <= 0) 443 return; 444 } 445 446 { 447 VGint y = (stfb->height - sy) - 1, yStep = -1; 448 struct pipe_transfer *transfer; 449 450 transfer = pipe_get_transfer(pipe, strb->texture, 0, 0, 451 PIPE_TRANSFER_READ, 452 0, 0, sx + width, stfb->height - sy); 453 454 /* Do a row at a time to flip image data vertically */ 455 for (i = 0; i < height; i++) { 456#if 0 457 debug_printf("%d-%d == %d\n", sy, height, y); 458#endif 459 pipe_get_tile_rgba(pipe, transfer, sx, y, width, 1, df); 460 y += yStep; 461 _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, 462 dst + yoffset + xoffset); 463 dst += dataStride; 464 } 465 466 pipe->transfer_destroy(pipe, transfer); 467 } 468} 469 470void vegaCopyPixels(VGint dx, VGint dy, 471 VGint sx, VGint sy, 472 VGint width, VGint height) 473{ 474 struct vg_context *ctx = vg_current_context(); 475 struct st_framebuffer *stfb = ctx->draw_buffer; 476 struct st_renderbuffer *strb = stfb->strb; 477 478 if (width <= 0 || height <= 0) { 479 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 480 return; 481 } 482 483 /* do nothing if we copy from outside the fb */ 484 if (dx >= (VGint)stfb->width || dy >= (VGint)stfb->height || 485 sx >= (VGint)stfb->width || sy >= (VGint)stfb->height) 486 return; 487 488 vg_validate_state(ctx); 489 /* make sure rendering has completed */ 490 vgFinish(); 491 492 vg_copy_surface(ctx, strb->surface, dx, dy, 493 strb->surface, sx, sy, width, height); 494} 495