u_surface.c revision 8b0c217f2bc123bffd25cc4977d6abb1b3fa8186
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/** 28 * @file 29 * Surface utility functions. 30 * 31 * @author Brian Paul 32 */ 33 34 35#include "pipe/p_defines.h" 36#include "pipe/p_screen.h" 37#include "pipe/p_state.h" 38 39#include "util/u_format.h" 40#include "util/u_inlines.h" 41#include "util/u_memory.h" 42#include "util/u_rect.h" 43#include "util/u_surface.h" 44 45 46/** 47 * Helper to quickly create an RGBA rendering surface of a certain size. 48 * \param textureOut returns the new texture 49 * \param surfaceOut returns the new surface 50 * \return TRUE for success, FALSE if failure 51 */ 52boolean 53util_create_rgba_surface(struct pipe_screen *screen, 54 uint width, uint height, 55 uint bind, 56 struct pipe_resource **textureOut, 57 struct pipe_surface **surfaceOut) 58{ 59 static const enum pipe_format rgbaFormats[] = { 60 PIPE_FORMAT_B8G8R8A8_UNORM, 61 PIPE_FORMAT_A8R8G8B8_UNORM, 62 PIPE_FORMAT_A8B8G8R8_UNORM, 63 PIPE_FORMAT_NONE 64 }; 65 const uint target = PIPE_TEXTURE_2D; 66 enum pipe_format format = PIPE_FORMAT_NONE; 67 struct pipe_resource templ; 68 uint i; 69 70 /* Choose surface format */ 71 for (i = 0; rgbaFormats[i]; i++) { 72 if (screen->is_format_supported(screen, rgbaFormats[i], 73 target, bind, 0)) { 74 format = rgbaFormats[i]; 75 break; 76 } 77 } 78 if (format == PIPE_FORMAT_NONE) 79 return FALSE; /* unable to get an rgba format!?! */ 80 81 /* create texture */ 82 memset(&templ, 0, sizeof(templ)); 83 templ.target = target; 84 templ.format = format; 85 templ.last_level = 0; 86 templ.width0 = width; 87 templ.height0 = height; 88 templ.depth0 = 1; 89 templ.bind = bind; 90 91 *textureOut = screen->resource_create(screen, &templ); 92 if (!*textureOut) 93 return FALSE; 94 95 /* create surface / view into texture */ 96 *surfaceOut = screen->get_tex_surface(screen, 97 *textureOut, 98 0, 0, 0, 99 bind); 100 if (!*surfaceOut) { 101 pipe_resource_reference(textureOut, NULL); 102 return FALSE; 103 } 104 105 return TRUE; 106} 107 108 109/** 110 * Release the surface and texture from util_create_rgba_surface(). 111 */ 112void 113util_destroy_rgba_surface(struct pipe_resource *texture, 114 struct pipe_surface *surface) 115{ 116 pipe_surface_reference(&surface, NULL); 117 pipe_resource_reference(&texture, NULL); 118} 119 120 121 122/** 123 * Fallback function for pipe->surface_copy(). 124 * Note: (X,Y)=(0,0) is always the upper-left corner. 125 * if do_flip, flip the image vertically on its way from src rect to dst rect. 126 */ 127void 128util_surface_copy(struct pipe_context *pipe, 129 boolean do_flip, 130 struct pipe_surface *dst, 131 unsigned dst_x, unsigned dst_y, 132 struct pipe_surface *src, 133 unsigned src_x, unsigned src_y, 134 unsigned w, unsigned h) 135{ 136 struct pipe_transfer *src_trans, *dst_trans; 137 void *dst_map; 138 const void *src_map; 139 enum pipe_format src_format, dst_format; 140 141 assert(src->texture && dst->texture); 142 if (!src->texture || !dst->texture) 143 return; 144 145 src_format = src->texture->format; 146 dst_format = dst->texture->format; 147 148 src_trans = pipe_get_transfer(pipe, 149 src->texture, 150 src->face, 151 src->level, 152 src->zslice, 153 PIPE_TRANSFER_READ, 154 src_x, src_y, w, h); 155 156 dst_trans = pipe_get_transfer(pipe, 157 dst->texture, 158 dst->face, 159 dst->level, 160 dst->zslice, 161 PIPE_TRANSFER_WRITE, 162 dst_x, dst_y, w, h); 163 164 assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format)); 165 assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format)); 166 assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format)); 167 168 src_map = pipe->transfer_map(pipe, src_trans); 169 dst_map = pipe->transfer_map(pipe, dst_trans); 170 171 assert(src_map); 172 assert(dst_map); 173 174 if (src_map && dst_map) { 175 /* If do_flip, invert src_y position and pass negative src stride */ 176 util_copy_rect(dst_map, 177 dst_format, 178 dst_trans->stride, 179 0, 0, 180 w, h, 181 src_map, 182 do_flip ? -(int) src_trans->stride : src_trans->stride, 183 0, 184 do_flip ? h - 1 : 0); 185 } 186 187 pipe->transfer_unmap(pipe, src_trans); 188 pipe->transfer_unmap(pipe, dst_trans); 189 190 pipe->transfer_destroy(pipe, src_trans); 191 pipe->transfer_destroy(pipe, dst_trans); 192} 193 194 195 196#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8)) 197 198 199/** 200 * Fallback for pipe->surface_fill() function. 201 */ 202void 203util_surface_fill(struct pipe_context *pipe, 204 struct pipe_surface *dst, 205 unsigned dstx, unsigned dsty, 206 unsigned width, unsigned height, unsigned value) 207{ 208 struct pipe_transfer *dst_trans; 209 void *dst_map; 210 211 assert(dst->texture); 212 if (!dst->texture) 213 return; 214 dst_trans = pipe_get_transfer(pipe, 215 dst->texture, 216 dst->face, 217 dst->level, 218 dst->zslice, 219 PIPE_TRANSFER_WRITE, 220 dstx, dsty, width, height); 221 222 dst_map = pipe->transfer_map(pipe, dst_trans); 223 224 assert(dst_map); 225 226 if (dst_map) { 227 assert(dst_trans->stride > 0); 228 229 switch (util_format_get_blocksize(dst->texture->format)) { 230 case 1: 231 case 2: 232 case 4: 233 util_fill_rect(dst_map, dst->texture->format, 234 dst_trans->stride, 235 0, 0, width, height, value); 236 break; 237 case 8: 238 { 239 /* expand the 4-byte clear value to an 8-byte value */ 240 ushort *row = (ushort *) dst_map; 241 ushort val0 = UBYTE_TO_USHORT((value >> 0) & 0xff); 242 ushort val1 = UBYTE_TO_USHORT((value >> 8) & 0xff); 243 ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff); 244 ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff); 245 unsigned i, j; 246 val0 = (val0 << 8) | val0; 247 val1 = (val1 << 8) | val1; 248 val2 = (val2 << 8) | val2; 249 val3 = (val3 << 8) | val3; 250 for (i = 0; i < height; i++) { 251 for (j = 0; j < width; j++) { 252 row[j*4+0] = val0; 253 row[j*4+1] = val1; 254 row[j*4+2] = val2; 255 row[j*4+3] = val3; 256 } 257 row += dst_trans->stride/2; 258 } 259 } 260 break; 261 default: 262 assert(0); 263 break; 264 } 265 } 266 267 pipe->transfer_unmap(pipe, dst_trans); 268 pipe->transfer_destroy(pipe, dst_trans); 269} 270