00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "st_context.h"
00029 #include "st_format.h"
00030 #include "st_public.h"
00031 #include "st_texture.h"
00032 #include "st_cb_fbo.h"
00033 #include "main/enums.h"
00034 #include "main/teximage.h"
00035
00036 #undef Elements
00037
00038 #include "pipe/p_state.h"
00039 #include "pipe/p_context.h"
00040 #include "pipe/p_defines.h"
00041 #include "pipe/p_inlines.h"
00042 #include "pipe/p_inlines.h"
00043 #include "util/u_rect.h"
00044
00045
00046 #define DBG if(0) printf
00047
00048 #if 0
00049 static GLenum
00050 target_to_target(GLenum target)
00051 {
00052 switch (target) {
00053 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
00054 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
00055 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
00056 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
00057 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
00058 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
00059 return GL_TEXTURE_CUBE_MAP_ARB;
00060 default:
00061 return target;
00062 }
00063 }
00064 #endif
00065
00066
00073 struct pipe_texture *
00074 st_texture_create(struct st_context *st,
00075 enum pipe_texture_target target,
00076 enum pipe_format format,
00077 GLuint last_level,
00078 GLuint width0,
00079 GLuint height0,
00080 GLuint depth0,
00081 GLuint compress_byte,
00082 GLuint usage )
00083 {
00084 struct pipe_texture pt, *newtex;
00085 struct pipe_screen *screen = st->pipe->screen;
00086
00087 assert(target <= PIPE_TEXTURE_CUBE);
00088
00089 DBG("%s target %s format %s last_level %d\n", __FUNCTION__,
00090 _mesa_lookup_enum_by_nr(target),
00091 _mesa_lookup_enum_by_nr(format), last_level);
00092
00093 assert(format);
00094 assert(screen->is_format_supported(screen, format, target,
00095 PIPE_TEXTURE_USAGE_SAMPLER, 0));
00096
00097 memset(&pt, 0, sizeof(pt));
00098 pt.target = target;
00099 pt.format = format;
00100 pt.last_level = last_level;
00101 pt.width[0] = width0;
00102 pt.height[0] = height0;
00103 pt.depth[0] = depth0;
00104 pt.compressed = compress_byte ? 1 : 0;
00105 pf_get_block(format, &pt.block);
00106 pt.tex_usage = usage;
00107
00108 newtex = screen->texture_create(screen, &pt);
00109
00110 assert(!newtex || newtex->refcount == 1);
00111
00112 return newtex;
00113 }
00114
00115
00122 GLboolean
00123 st_texture_match_image(const struct pipe_texture *pt,
00124 const struct gl_texture_image *image,
00125 GLuint face, GLuint level)
00126 {
00127
00128
00129 if (image->Border)
00130 return GL_FALSE;
00131
00132 if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format ||
00133 image->IsCompressed != pt->compressed)
00134 return GL_FALSE;
00135
00136
00137
00138
00139
00140 if (image->Width != pt->width[level] ||
00141 image->Height != pt->height[level] ||
00142 image->Depth != pt->depth[level])
00143 return GL_FALSE;
00144
00145 return GL_TRUE;
00146 }
00147
00148
00149 #if 000
00150
00151
00152
00153
00154
00155
00156 const GLuint *
00157 st_texture_depth_offsets(struct pipe_texture *pt, GLuint level)
00158 {
00159 static const GLuint zero = 0;
00160
00161 if (pt->target != PIPE_TEXTURE_3D || pt->level[level].nr_images == 1)
00162 return &zero;
00163 else
00164 return pt->level[level].image_offset;
00165 }
00166
00167
00172 GLuint
00173 st_texture_image_offset(const struct pipe_texture * pt,
00174 GLuint face, GLuint level)
00175 {
00176 if (pt->target == PIPE_TEXTURE_CUBE)
00177 return (pt->level[level].level_offset +
00178 pt->level[level].image_offset[face] * pt->cpp);
00179 else
00180 return pt->level[level].level_offset;
00181 }
00182 #endif
00183
00184
00191 GLubyte *
00192 st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
00193 GLuint zoffset,
00194 GLuint flags )
00195 {
00196 struct pipe_screen *screen = st->pipe->screen;
00197 struct pipe_texture *pt = stImage->pt;
00198 DBG("%s \n", __FUNCTION__);
00199
00200 stImage->surface = screen->get_tex_surface(screen, pt, stImage->face,
00201 stImage->level, zoffset,
00202 flags);
00203
00204 if (stImage->surface)
00205 return screen->surface_map(screen, stImage->surface, flags);
00206 else
00207 return NULL;
00208 }
00209
00210
00211 void
00212 st_texture_image_unmap(struct st_context *st,
00213 struct st_texture_image *stImage)
00214 {
00215 struct pipe_screen *screen = st->pipe->screen;
00216
00217 DBG("%s\n", __FUNCTION__);
00218
00219 screen->surface_unmap(screen, stImage->surface);
00220
00221 pipe_surface_reference(&stImage->surface, NULL);
00222 }
00223
00224
00225
00234 static void
00235 st_surface_data(struct pipe_context *pipe,
00236 struct pipe_surface *dst,
00237 unsigned dstx, unsigned dsty,
00238 const void *src, unsigned src_stride,
00239 unsigned srcx, unsigned srcy, unsigned width, unsigned height)
00240 {
00241 struct pipe_screen *screen = pipe->screen;
00242 void *map = screen->surface_map(screen, dst, PIPE_BUFFER_USAGE_CPU_WRITE);
00243
00244 pipe_copy_rect(map,
00245 &dst->block,
00246 dst->stride,
00247 dstx, dsty,
00248 width, height,
00249 src, src_stride,
00250 srcx, srcy);
00251
00252 screen->surface_unmap(screen, dst);
00253 }
00254
00255
00256
00257
00258 void
00259 st_texture_image_data(struct pipe_context *pipe,
00260 struct pipe_texture *dst,
00261 GLuint face,
00262 GLuint level,
00263 void *src,
00264 GLuint src_row_stride, GLuint src_image_stride)
00265 {
00266 struct pipe_screen *screen = pipe->screen;
00267 GLuint depth = dst->depth[level];
00268 GLuint i;
00269 const GLubyte *srcUB = src;
00270 struct pipe_surface *dst_surface;
00271
00272 DBG("%s\n", __FUNCTION__);
00273 for (i = 0; i < depth; i++) {
00274 dst_surface = screen->get_tex_surface(screen, dst, face, level, i,
00275 PIPE_BUFFER_USAGE_CPU_WRITE);
00276
00277 st_surface_data(pipe, dst_surface,
00278 0, 0,
00279 srcUB,
00280 src_row_stride,
00281 0, 0,
00282 dst->width[level], dst->height[level]);
00283
00284 screen->tex_surface_release(screen, &dst_surface);
00285
00286 srcUB += src_image_stride;
00287 }
00288 }
00289
00290
00291
00292
00293 void
00294 st_texture_image_copy(struct pipe_context *pipe,
00295 struct pipe_texture *dst, GLuint dstLevel,
00296 struct pipe_texture *src,
00297 GLuint face)
00298 {
00299 struct pipe_screen *screen = pipe->screen;
00300 GLuint width = dst->width[dstLevel];
00301 GLuint height = dst->height[dstLevel];
00302 GLuint depth = dst->depth[dstLevel];
00303 struct pipe_surface *src_surface;
00304 struct pipe_surface *dst_surface;
00305 GLuint i;
00306
00307 for (i = 0; i < depth; i++) {
00308 GLuint srcLevel;
00309
00310
00311 for (srcLevel = 0; srcLevel <= src->last_level; srcLevel++) {
00312 if (src->width[srcLevel] == width &&
00313 src->height[srcLevel] == height) {
00314 break;
00315 }
00316 }
00317 assert(src->width[srcLevel] == width);
00318 assert(src->height[srcLevel] == height);
00319
00320 #if 0
00321 {
00322 src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i,
00323 PIPE_BUFFER_USAGE_CPU_READ);
00324 ubyte *map = screen->surface_map(screen, src_surface, PIPE_BUFFER_USAGE_CPU_READ);
00325 map += src_surface->width * src_surface->height * 4 / 2;
00326 printf("%s center pixel: %d %d %d %d (pt %p[%d] -> %p[%d])\n",
00327 __FUNCTION__,
00328 map[0], map[1], map[2], map[3],
00329 src, srcLevel, dst, dstLevel);
00330
00331 screen->surface_unmap(screen, src_surface);
00332 pipe_surface_reference(&src_surface, NULL);
00333 }
00334 #endif
00335
00336 dst_surface = screen->get_tex_surface(screen, dst, face, dstLevel, i,
00337 PIPE_BUFFER_USAGE_GPU_WRITE);
00338
00339 src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i,
00340 PIPE_BUFFER_USAGE_GPU_READ);
00341
00342 pipe->surface_copy(pipe,
00343 FALSE,
00344 dst_surface,
00345 0, 0,
00346 src_surface,
00347 0, 0,
00348 width, height);
00349
00350 screen->tex_surface_release(screen, &src_surface);
00351 screen->tex_surface_release(screen, &dst_surface);
00352 }
00353 }
00354
00355
00357 int
00358 st_bind_teximage(struct st_framebuffer *stfb, uint surfIndex,
00359 int target, int format, int level)
00360 {
00361 GET_CURRENT_CONTEXT(ctx);
00362 struct st_context *st = ctx->st;
00363 struct pipe_context *pipe = st->pipe;
00364 struct pipe_screen *screen = pipe->screen;
00365 const GLuint unit = ctx->Texture.CurrentUnit;
00366 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
00367 struct gl_texture_object *texObj;
00368 struct gl_texture_image *texImage;
00369 struct st_texture_image *stImage;
00370 struct st_renderbuffer *strb;
00371 GLint face = 0, slice = 0;
00372
00373 assert(surfIndex <= ST_SURFACE_DEPTH);
00374
00375 strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
00376
00377 if (strb->texture_save || strb->surface_save) {
00378
00379 return 0;
00380 }
00381
00382 if (target == ST_TEXTURE_2D) {
00383 texObj = texUnit->Current2D;
00384 texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, level);
00385 stImage = st_texture_image(texImage);
00386 }
00387 else {
00388
00389 return 0;
00390 }
00391
00392 st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
00393
00394
00395 pipe_texture_reference(&strb->texture_save, strb->texture);
00396 pipe_surface_reference(&strb->surface_save, strb->surface);
00397
00398
00399 pipe_texture_reference(&strb->texture, stImage->pt);
00400 strb->surface = screen->get_tex_surface(screen, strb->texture,
00401 face, level, slice,
00402 (PIPE_BUFFER_USAGE_GPU_READ |
00403 PIPE_BUFFER_USAGE_GPU_WRITE));
00404
00405 st->dirty.st |= ST_NEW_FRAMEBUFFER;
00406
00407 return 1;
00408 }
00409
00410
00412 int
00413 st_release_teximage(struct st_framebuffer *stfb, uint surfIndex,
00414 int target, int format, int level)
00415 {
00416 GET_CURRENT_CONTEXT(ctx);
00417 struct st_context *st = ctx->st;
00418 struct st_renderbuffer *strb;
00419
00420 assert(surfIndex <= ST_SURFACE_DEPTH);
00421
00422 strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer);
00423
00424 if (!strb->texture_save || !strb->surface_save) {
00425
00426 return 0;
00427 }
00428
00429 st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
00430
00431
00432 pipe_surface_reference(&strb->surface, strb->surface_save);
00433 pipe_texture_reference(&strb->texture, strb->texture_save);
00434
00435 pipe_surface_reference(&strb->surface_save, NULL);
00436 pipe_texture_reference(&strb->texture_save, NULL);
00437
00438 st->dirty.st |= ST_NEW_FRAMEBUFFER;
00439
00440 return 1;
00441 }