u_rect.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00033 #include "pipe/p_defines.h"
00034 #include "pipe/p_format.h"
00035 #include "pipe/p_context.h"
00036 #include "pipe/p_screen.h"
00037 #include "util/u_rect.h"
00038 
00039 
00045 void
00046 pipe_copy_rect(ubyte * dst,
00047                const struct pipe_format_block *block,
00048                unsigned dst_stride,
00049                unsigned dst_x,
00050                unsigned dst_y,
00051                unsigned width,
00052                unsigned height,
00053                const ubyte * src,
00054                int src_stride,
00055                unsigned src_x, 
00056                int src_y)
00057 {
00058    unsigned i;
00059    int src_stride_pos = src_stride < 0 ? -src_stride : src_stride;
00060 
00061    assert(block->size > 0);
00062    assert(block->width > 0);
00063    assert(block->height > 0);
00064    assert(src_x >= 0);
00065    assert(src_y >= 0);
00066    assert(dst_x >= 0);
00067    assert(dst_y >= 0);
00068 
00069    dst_x /= block->width;
00070    dst_y /= block->height;
00071    width = (width + block->width - 1)/block->width;
00072    height = (height + block->height - 1)/block->height;
00073    src_x /= block->width;
00074    src_y /= block->height;
00075    
00076    dst += dst_x * block->size;
00077    src += src_x * block->size;
00078    dst += dst_y * dst_stride;
00079    src += src_y * src_stride_pos;
00080    width *= block->size;
00081 
00082    if (width == dst_stride && width == src_stride)
00083       memcpy(dst, src, height * width);
00084    else {
00085       for (i = 0; i < height; i++) {
00086          memcpy(dst, src, width);
00087          dst += dst_stride;
00088          src += src_stride;
00089       }
00090    }
00091 }
00092 
00093 void
00094 pipe_fill_rect(ubyte * dst,
00095                const struct pipe_format_block *block,
00096                unsigned dst_stride,
00097                unsigned dst_x,
00098                unsigned dst_y,
00099                unsigned width,
00100                unsigned height,
00101                uint32_t value)
00102 {
00103    unsigned i, j;
00104    unsigned width_size;
00105 
00106    assert(block->size > 0);
00107    assert(block->width > 0);
00108    assert(block->height > 0);
00109    assert(dst_x >= 0);
00110    assert(dst_y >= 0);
00111 
00112    dst_x /= block->width;
00113    dst_y /= block->height;
00114    width = (width + block->width - 1)/block->width;
00115    height = (height + block->height - 1)/block->height;
00116    
00117    dst += dst_x * block->size;
00118    dst += dst_y * dst_stride;
00119    width_size = width * block->size;
00120    
00121    switch (block->size) {
00122    case 1:
00123       if(dst_stride == width_size)
00124          memset(dst, (ubyte) value, height * width_size);
00125       else {
00126          for (i = 0; i < height; i++) {
00127             memset(dst, (ubyte) value, width_size);
00128             dst += dst_stride;
00129          }
00130       }
00131       break;
00132    case 2:
00133       for (i = 0; i < height; i++) {
00134          uint16_t *row = (uint16_t *)dst;
00135          for (j = 0; j < width; j++)
00136             *row++ = (uint16_t) value;
00137          dst += dst_stride;
00138       }
00139       break;
00140    case 4:
00141       for (i = 0; i < height; i++) {
00142          uint32_t *row = (uint32_t *)dst;
00143          for (j = 0; j < width; j++)
00144             *row++ = value;
00145          dst += dst_stride;
00146       }
00147       break;
00148    default:
00149          assert(0);
00150          break;
00151    }
00152 }
00153 
00154 
00155 
00162 void
00163 util_surface_copy(struct pipe_context *pipe,
00164                   boolean do_flip,
00165                   struct pipe_surface *dst,
00166                   unsigned dst_x, unsigned dst_y,
00167                   struct pipe_surface *src,
00168                   unsigned src_x, unsigned src_y, 
00169                   unsigned w, unsigned h)
00170 {
00171    struct pipe_screen *screen = pipe->screen;
00172    struct pipe_surface *new_src = NULL, *new_dst = NULL;
00173    void *dst_map;
00174    const void *src_map;
00175 
00176    assert(dst->block.size == src->block.size);
00177    assert(dst->block.width == src->block.width);
00178    assert(dst->block.height == src->block.height);
00179 
00180    if ((src->usage & PIPE_BUFFER_USAGE_CPU_READ) == 0) {
00181       /* Need to create new src surface which is CPU readable */
00182       assert(src->texture);
00183       if (!src->texture)
00184          return;
00185       new_src = screen->get_tex_surface(screen,
00186                                         src->texture,
00187                                         src->face,
00188                                         src->level,
00189                                         src->zslice,
00190                                         PIPE_BUFFER_USAGE_CPU_READ);
00191       src = new_src;
00192    }
00193 
00194    if ((dst->usage & PIPE_BUFFER_USAGE_CPU_WRITE) == 0) {
00195       /* Need to create new dst surface which is CPU writable */
00196       assert(dst->texture);
00197       if (!dst->texture)
00198          return;
00199       new_dst = screen->get_tex_surface(screen,
00200                                         dst->texture,
00201                                         dst->face,
00202                                         dst->level,
00203                                         dst->zslice,
00204                                         PIPE_BUFFER_USAGE_CPU_WRITE);
00205       dst = new_dst;
00206    }
00207 
00208    src_map = pipe->screen->surface_map(screen,
00209                                        src, PIPE_BUFFER_USAGE_CPU_READ);
00210    dst_map = pipe->screen->surface_map(screen,
00211                                        dst, PIPE_BUFFER_USAGE_CPU_WRITE);
00212 
00213    assert(src_map);
00214    assert(dst_map);
00215 
00216    if (src_map && dst_map) {
00217       /* If do_flip, invert src_y position and pass negative src stride */
00218       pipe_copy_rect(dst_map,
00219                      &dst->block,
00220                      dst->stride,
00221                      dst_x, dst_y,
00222                      w, h,
00223                      src_map,
00224                      do_flip ? -(int) src->stride : src->stride,
00225                      src_x,
00226                      do_flip ? src_y + h - 1 : src_y);
00227    }
00228 
00229    pipe->screen->surface_unmap(pipe->screen, src);
00230    pipe->screen->surface_unmap(pipe->screen, dst);
00231 
00232    if (new_src)
00233       screen->tex_surface_release(screen, &new_src);
00234    if (new_dst)
00235       screen->tex_surface_release(screen, &new_dst);
00236 }
00237 
00238 
00239 
00240 static void *
00241 get_pointer(struct pipe_surface *dst, void *dst_map, unsigned x, unsigned y)
00242 {
00243    return (char *)dst_map
00244       + y / dst->block.height * dst->stride
00245       + x / dst->block.width * dst->block.size;
00246 }
00247 
00248 
00249 #define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
00250 
00251 
00256 void
00257 util_surface_fill(struct pipe_context *pipe,
00258                   struct pipe_surface *dst,
00259                   unsigned dstx, unsigned dsty,
00260                   unsigned width, unsigned height, unsigned value)
00261 {
00262    struct pipe_screen *screen = pipe->screen;
00263    struct pipe_surface *new_dst = NULL;
00264    void *dst_map;
00265 
00266    if ((dst->usage & PIPE_BUFFER_USAGE_CPU_WRITE) == 0) {
00267       /* Need to create new dst surface which is CPU writable */
00268       assert(dst->texture);
00269       if (!dst->texture)
00270          return;
00271       new_dst = screen->get_tex_surface(screen,
00272                                         dst->texture,
00273                                         dst->face,
00274                                         dst->level,
00275                                         dst->zslice,
00276                                         PIPE_BUFFER_USAGE_CPU_WRITE);
00277       dst = new_dst;
00278    }
00279 
00280    dst_map = pipe->screen->surface_map(screen,
00281                                        dst, PIPE_BUFFER_USAGE_CPU_WRITE);
00282 
00283    assert(dst_map);
00284 
00285    if (dst_map) {
00286       assert(dst->stride > 0);
00287 
00288       switch (dst->block.size) {
00289       case 1:
00290       case 2:
00291       case 4:
00292          pipe_fill_rect(dst_map, &dst->block, dst->stride,
00293                         dstx, dsty, width, height, value);
00294          break;
00295       case 8:
00296          {
00297             /* expand the 4-byte clear value to an 8-byte value */
00298             ushort *row = (ushort *) get_pointer(dst, dst_map, dstx, dsty);
00299             ushort val0 = UBYTE_TO_USHORT((value >>  0) & 0xff);
00300             ushort val1 = UBYTE_TO_USHORT((value >>  8) & 0xff);
00301             ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
00302             ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
00303             unsigned i, j;
00304             val0 = (val0 << 8) | val0;
00305             val1 = (val1 << 8) | val1;
00306             val2 = (val2 << 8) | val2;
00307             val3 = (val3 << 8) | val3;
00308             for (i = 0; i < height; i++) {
00309                for (j = 0; j < width; j++) {
00310                   row[j*4+0] = val0;
00311                   row[j*4+1] = val1;
00312                   row[j*4+2] = val2;
00313                   row[j*4+3] = val3;
00314                }
00315                row += dst->stride/2;
00316             }
00317          }
00318          break;
00319       default:
00320          assert(0);
00321          break;
00322       }
00323    }
00324 
00325    pipe->screen->surface_unmap(pipe->screen, dst);
00326 
00327    if (new_dst)
00328       screen->tex_surface_release(screen, &new_dst);
00329 }

Generated on Tue Sep 29 06:25:15 2009 for Gallium3D by  doxygen 1.5.4