u_surface.c revision a6e5c6c000df8655de3b41d5809547bb41c88c23
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_rect.h" 42#include "util/u_surface.h" 43#include "util/u_pack_color.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, 0, 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->resource_copy_region(). 124 * Note: (X,Y)=(0,0) is always the upper-left corner. 125 */ 126void 127util_resource_copy_region(struct pipe_context *pipe, 128 struct pipe_resource *dst, 129 struct pipe_subresource subdst, 130 unsigned dst_x, unsigned dst_y, unsigned dst_z, 131 struct pipe_resource *src, 132 struct pipe_subresource subsrc, 133 unsigned src_x, unsigned src_y, unsigned src_z, 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 && dst); 142 if (!src || !dst) 143 return; 144 145 src_format = src->format; 146 dst_format = dst->format; 147 148 src_trans = pipe_get_transfer(pipe, 149 src, 150 subsrc.face, 151 subsrc.level, 152 src_z, 153 PIPE_TRANSFER_READ, 154 src_x, src_y, w, h); 155 156 dst_trans = pipe_get_transfer(pipe, 157 dst, 158 subdst.face, 159 subdst.level, 160 src_z, 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 util_copy_rect(dst_map, 176 dst_format, 177 dst_trans->stride, 178 0, 0, 179 w, h, 180 src_map, 181 src_trans->stride, 182 0, 183 0); 184 } 185 186 pipe->transfer_unmap(pipe, src_trans); 187 pipe->transfer_unmap(pipe, dst_trans); 188 189 pipe->transfer_destroy(pipe, src_trans); 190 pipe->transfer_destroy(pipe, dst_trans); 191} 192 193 194 195#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8)) 196 197 198/** 199 * Fallback for pipe->clear_render_target() function. 200 * XXX this looks too hackish to be really useful. 201 * cpp > 4 looks like a gross hack at best... 202 * and we're missing the equivalent clear_depth_stencil fallback. 203 * Plus can't use these transfer fallbacks when clearing 204 * multisampled surfaces for instance. 205 */ 206void 207util_clear_render_target(struct pipe_context *pipe, 208 struct pipe_surface *dst, 209 const float *rgba, 210 unsigned dstx, unsigned dsty, 211 unsigned width, unsigned height) 212{ 213 struct pipe_transfer *dst_trans; 214 void *dst_map; 215 union util_color uc; 216 217 assert(dst->texture); 218 if (!dst->texture) 219 return; 220 util_pack_color(rgba, dst->texture->format, &uc); 221 dst_trans = pipe_get_transfer(pipe, 222 dst->texture, 223 dst->face, 224 dst->level, 225 dst->zslice, 226 PIPE_TRANSFER_WRITE, 227 dstx, dsty, width, height); 228 229 dst_map = pipe->transfer_map(pipe, dst_trans); 230 231 assert(dst_map); 232 233 if (dst_map) { 234 assert(dst_trans->stride > 0); 235 236 switch (util_format_get_blocksize(dst->texture->format)) { 237 case 1: 238 case 2: 239 case 4: 240 util_pack_color(rgba, dst->texture->format, &uc); 241 util_fill_rect(dst_map, dst->texture->format, 242 dst_trans->stride, 243 0, 0, width, height, uc.ui); 244 break; 245 case 8: 246 { 247 /* expand the 4-byte clear value to an 8-byte value */ 248 /* should probably not convert back from ubyte but not 249 sure what this code really achieved since it doesn't even 250 check for format type... */ 251 ushort *row = (ushort *) dst_map; 252 ushort val0 = UBYTE_TO_USHORT((uc.ui >> 0) & 0xff); 253 ushort val1 = UBYTE_TO_USHORT((uc.ui >> 8) & 0xff); 254 ushort val2 = UBYTE_TO_USHORT((uc.ui >> 16) & 0xff); 255 ushort val3 = UBYTE_TO_USHORT((uc.ui >> 24) & 0xff); 256 unsigned i, j; 257 val0 = (val0 << 8) | val0; 258 val1 = (val1 << 8) | val1; 259 val2 = (val2 << 8) | val2; 260 val3 = (val3 << 8) | val3; 261 for (i = 0; i < height; i++) { 262 for (j = 0; j < width; j++) { 263 row[j*4+0] = val0; 264 row[j*4+1] = val1; 265 row[j*4+2] = val2; 266 row[j*4+3] = val3; 267 } 268 row += dst_trans->stride/2; 269 } 270 } 271 break; 272 default: 273 assert(0); 274 break; 275 } 276 } 277 278 pipe->transfer_unmap(pipe, dst_trans); 279 pipe->transfer_destroy(pipe, dst_trans); 280} 281