api_images.c revision 93a7e6d94e09a25bdbe31eedb0759e390ccb6a86
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 41static INLINE VGboolean supported_image_format(VGImageFormat format) 42{ 43 switch(format) { 44 case VG_sRGBX_8888: 45 case VG_sRGBA_8888: 46 case VG_sRGBA_8888_PRE: 47 case VG_sRGB_565: 48 case VG_sRGBA_5551: 49 case VG_sRGBA_4444: 50 case VG_sL_8: 51 case VG_lRGBX_8888: 52 case VG_lRGBA_8888: 53 case VG_lRGBA_8888_PRE: 54 case VG_lL_8: 55 case VG_A_8: 56 case VG_BW_1: 57#ifdef OPENVG_VERSION_1_1 58 case VG_A_1: 59 case VG_A_4: 60#endif 61 case VG_sXRGB_8888: 62 case VG_sARGB_8888: 63 case VG_sARGB_8888_PRE: 64 case VG_sARGB_1555: 65 case VG_sARGB_4444: 66 case VG_lXRGB_8888: 67 case VG_lARGB_8888: 68 case VG_lARGB_8888_PRE: 69 case VG_sBGRX_8888: 70 case VG_sBGRA_8888: 71 case VG_sBGRA_8888_PRE: 72 case VG_sBGR_565: 73 case VG_sBGRA_5551: 74 case VG_sBGRA_4444: 75 case VG_lBGRX_8888: 76 case VG_lBGRA_8888: 77 case VG_lBGRA_8888_PRE: 78 case VG_sXBGR_8888: 79 case VG_sABGR_8888: 80 case VG_sABGR_8888_PRE: 81 case VG_sABGR_1555: 82 case VG_sABGR_4444: 83 case VG_lXBGR_8888: 84 case VG_lABGR_8888: 85 case VG_lABGR_8888_PRE: 86 return VG_TRUE; 87 default: 88 return VG_FALSE; 89 } 90 return VG_FALSE; 91} 92 93VGImage vegaCreateImage(VGImageFormat format, 94 VGint width, VGint height, 95 VGbitfield allowedQuality) 96{ 97 struct vg_context *ctx = vg_current_context(); 98 99 if (!supported_image_format(format)) { 100 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 101 return VG_INVALID_HANDLE; 102 } 103 if (width <= 0 || height <= 0) { 104 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 105 return VG_INVALID_HANDLE; 106 } 107 if (width > vgGeti(VG_MAX_IMAGE_WIDTH) || 108 height > vgGeti(VG_MAX_IMAGE_HEIGHT)) { 109 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 110 return VG_INVALID_HANDLE; 111 } 112 if (width * height > vgGeti(VG_MAX_IMAGE_PIXELS)) { 113 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 114 return VG_INVALID_HANDLE; 115 } 116 117 if (!(allowedQuality & ((VG_IMAGE_QUALITY_NONANTIALIASED | 118 VG_IMAGE_QUALITY_FASTER | 119 VG_IMAGE_QUALITY_BETTER)))) { 120 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 121 return VG_INVALID_HANDLE; 122 } 123 124 return (VGImage)image_create(format, width, height); 125} 126 127void vegaDestroyImage(VGImage image) 128{ 129 struct vg_context *ctx = vg_current_context(); 130 struct vg_image *img = (struct vg_image *)image; 131 132 if (image == VG_INVALID_HANDLE) { 133 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 134 return; 135 } 136 if (!vg_object_is_valid((void*)image, VG_OBJECT_IMAGE)) { 137 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 138 return; 139 } 140 image_destroy(img); 141} 142 143void vegaClearImage(VGImage image, 144 VGint x, VGint y, 145 VGint width, VGint height) 146{ 147 struct vg_context *ctx = vg_current_context(); 148 struct vg_image *img; 149 150 if (image == VG_INVALID_HANDLE) { 151 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 152 return; 153 } 154 if (width <= 0 || height <= 0) { 155 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 156 return; 157 } 158 159 img = (struct vg_image*)image; 160 161 if (x + width < 0 || y + height < 0) 162 return; 163 164 image_clear(img, x, y, width, height); 165 166} 167 168void vegaImageSubData(VGImage image, 169 const void * data, 170 VGint dataStride, 171 VGImageFormat dataFormat, 172 VGint x, VGint y, 173 VGint width, VGint height) 174{ 175 struct vg_context *ctx = vg_current_context(); 176 struct vg_image *img; 177 178 if (image == VG_INVALID_HANDLE) { 179 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 180 return; 181 } 182 if (!supported_image_format(dataFormat)) { 183 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 184 return; 185 } 186 if (width <= 0 || height <= 0 || !data || !is_aligned(data)) { 187 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 188 return; 189 } 190 191 img = (struct vg_image*)(image); 192 image_sub_data(img, data, dataStride, dataFormat, 193 x, y, width, height); 194} 195 196void vegaGetImageSubData(VGImage image, 197 void * data, 198 VGint dataStride, 199 VGImageFormat dataFormat, 200 VGint x, VGint y, 201 VGint width, VGint height) 202{ 203 struct vg_context *ctx = vg_current_context(); 204 struct vg_image *img; 205 206 if (image == VG_INVALID_HANDLE) { 207 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 208 return; 209 } 210 if (!supported_image_format(dataFormat)) { 211 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 212 return; 213 } 214 if (width <= 0 || height <= 0 || !data || !is_aligned(data)) { 215 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 216 return; 217 } 218 img = (struct vg_image*)image; 219 image_get_sub_data(img, data, dataStride, dataFormat, 220 x, y, width, height); 221} 222 223VGImage vegaChildImage(VGImage parent, 224 VGint x, VGint y, 225 VGint width, VGint height) 226{ 227 struct vg_context *ctx = vg_current_context(); 228 struct vg_image *p; 229 230 if (parent == VG_INVALID_HANDLE || 231 !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void*)parent) || 232 !vg_object_is_valid((void*)parent, VG_OBJECT_IMAGE)) { 233 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 234 return VG_INVALID_HANDLE; 235 } 236 if (width <= 0 || height <= 0 || x < 0 || y < 0) { 237 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 238 return VG_INVALID_HANDLE; 239 } 240 p = (struct vg_image *)parent; 241 if (x > p->width || y > p->height) { 242 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 243 return VG_INVALID_HANDLE; 244 } 245 if (x + width > p->width || y + height > p->height) { 246 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 247 return VG_INVALID_HANDLE; 248 } 249 250 return (VGImage)image_child_image(p, x, y, width, height); 251} 252 253VGImage vegaGetParent(VGImage image) 254{ 255 struct vg_context *ctx = vg_current_context(); 256 struct vg_image *img; 257 258 if (image == VG_INVALID_HANDLE) { 259 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 260 return VG_INVALID_HANDLE; 261 } 262 263 img = (struct vg_image*)image; 264 if (img->parent) 265 return (VGImage)img->parent; 266 else 267 return image; 268} 269 270void vegaCopyImage(VGImage dst, VGint dx, VGint dy, 271 VGImage src, VGint sx, VGint sy, 272 VGint width, VGint height, 273 VGboolean dither) 274{ 275 struct vg_context *ctx = vg_current_context(); 276 277 if (src == VG_INVALID_HANDLE || dst == VG_INVALID_HANDLE) { 278 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 279 return; 280 } 281 282 if (width <= 0 || height <= 0) { 283 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 284 return; 285 } 286 vg_validate_state(ctx); 287 image_copy((struct vg_image*)dst, dx, dy, 288 (struct vg_image*)src, sx, sy, 289 width, height, dither); 290} 291 292void vegaDrawImage(VGImage image) 293{ 294 struct vg_context *ctx = vg_current_context(); 295 296 if (!ctx) 297 return; 298 299 if (image == VG_INVALID_HANDLE) { 300 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 301 return; 302 } 303 304 vg_validate_state(ctx); 305 image_draw((struct vg_image*)image); 306} 307 308void vegaSetPixels(VGint dx, VGint dy, 309 VGImage src, VGint sx, VGint sy, 310 VGint width, VGint height) 311{ 312 struct vg_context *ctx = vg_current_context(); 313 314 vg_validate_state(ctx); 315 316 if (src == VG_INVALID_HANDLE) { 317 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 318 return; 319 } 320 if (width <= 0 || height <= 0) { 321 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 322 return; 323 } 324 image_set_pixels(dx, dy, (struct vg_image*)src, sx, sy, width, 325 height); 326} 327 328void vegaGetPixels(VGImage dst, VGint dx, VGint dy, 329 VGint sx, VGint sy, 330 VGint width, VGint height) 331{ 332 struct vg_context *ctx = vg_current_context(); 333 struct vg_image *img; 334 335 if (dst == VG_INVALID_HANDLE) { 336 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 337 return; 338 } 339 if (width <= 0 || height <= 0) { 340 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 341 return; 342 } 343 344 img = (struct vg_image*)dst; 345 346 image_get_pixels(img, dx, dy, 347 sx, sy, width, height); 348} 349 350void vegaWritePixels(const void * data, VGint dataStride, 351 VGImageFormat dataFormat, 352 VGint dx, VGint dy, 353 VGint width, VGint height) 354{ 355 struct vg_context *ctx = vg_current_context(); 356 struct pipe_context *pipe = ctx->pipe; 357 358 if (!supported_image_format(dataFormat)) { 359 vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); 360 return; 361 } 362 if (!data || !is_aligned(data)) { 363 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 364 return; 365 } 366 if (width <= 0 || height <= 0) { 367 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 368 return; 369 } 370 371 vg_validate_state(ctx); 372 { 373 struct vg_image *img = image_create(dataFormat, width, height); 374 image_sub_data(img, data, dataStride, dataFormat, 0, 0, 375 width, height); 376#if 0 377 struct matrix *matrix = &ctx->state.vg.image_user_to_surface_matrix; 378 matrix_translate(matrix, dx, dy); 379 image_draw(img); 380 matrix_translate(matrix, -dx, -dy); 381#else 382 /* this looks like a better approach */ 383 image_set_pixels(dx, dy, img, 0, 0, width, height); 384#endif 385 image_destroy(img); 386 } 387 /* make sure rendering has completed */ 388 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 389} 390 391void vegaReadPixels(void * data, VGint dataStride, 392 VGImageFormat dataFormat, 393 VGint sx, VGint sy, 394 VGint width, VGint height) 395{ 396 struct vg_context *ctx = vg_current_context(); 397 struct pipe_context *pipe = ctx->pipe; 398 399 struct st_framebuffer *stfb = ctx->draw_buffer; 400 struct st_renderbuffer *strb = stfb->strb; 401 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 402 403 VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; 404 VGfloat *df = (VGfloat*)temp; 405 VGint y = (fb->height - sy) - 1, yStep = -1; 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 height += sy; 434 sy = 0; 435 y = (fb->height - sy) - 1; 436 yoffset *= dataStride; 437 } 438 439 { 440 struct pipe_transfer *transfer; 441 442 transfer = pipe_get_transfer(pipe, strb->texture, 0, 0, 0, 443 PIPE_TRANSFER_READ, 444 0, 0, width, height); 445 446 /* Do a row at a time to flip image data vertically */ 447 for (i = 0; i < height; i++) { 448#if 0 449 debug_printf("%d-%d == %d\n", sy, height, y); 450#endif 451 pipe_get_tile_rgba(pipe, transfer, sx, y, width, 1, df); 452 y += yStep; 453 _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, 454 dst + yoffset + xoffset); 455 dst += dataStride; 456 } 457 458 pipe->transfer_destroy(pipe, transfer); 459 } 460} 461 462void vegaCopyPixels(VGint dx, VGint dy, 463 VGint sx, VGint sy, 464 VGint width, VGint height) 465{ 466 struct vg_context *ctx = vg_current_context(); 467 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 468 struct st_renderbuffer *strb = ctx->draw_buffer->strb; 469 470 if (width <= 0 || height <= 0) { 471 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 472 return; 473 } 474 475 /* do nothing if we copy from outside the fb */ 476 if (dx >= (VGint)fb->width || dy >= (VGint)fb->height || 477 sx >= (VGint)fb->width || sy >= (VGint)fb->height) 478 return; 479 480 vg_validate_state(ctx); 481 /* make sure rendering has completed */ 482 vgFinish(); 483 484 vg_copy_surface(ctx, strb->surface, dx, dy, 485 strb->surface, sx, sy, width, height); 486} 487