Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4
 * All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice (including the
15
 * next paragraph) shall be included in all copies or substantial portions
16
 * of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 **************************************************************************/
27
 
28
#include 
29
 
30
#include "st_context.h"
31
#include "st_format.h"
32
#include "st_texture.h"
33
#include "st_cb_fbo.h"
34
#include "main/enums.h"
35
 
36
#include "pipe/p_state.h"
37
#include "pipe/p_context.h"
38
#include "pipe/p_defines.h"
39
#include "util/u_inlines.h"
40
#include "util/u_format.h"
41
#include "util/u_rect.h"
42
#include "util/u_math.h"
43
 
44
 
45
#define DBG if(0) printf
46
 
47
 
48
/**
49
 * Allocate a new pipe_resource object
50
 * width0, height0, depth0 are the dimensions of the level 0 image
51
 * (the highest resolution).  last_level indicates how many mipmap levels
52
 * to allocate storage for.  For non-mipmapped textures, this will be zero.
53
 */
54
struct pipe_resource *
55
st_texture_create(struct st_context *st,
56
                  enum pipe_texture_target target,
57
		  enum pipe_format format,
58
		  GLuint last_level,
59
		  GLuint width0,
60
		  GLuint height0,
61
		  GLuint depth0,
62
                  GLuint layers,
63
                  GLuint nr_samples,
64
                  GLuint bind )
65
{
66
   struct pipe_resource pt, *newtex;
67
   struct pipe_screen *screen = st->pipe->screen;
68
 
69
   assert(target < PIPE_MAX_TEXTURE_TYPES);
70
   assert(width0 > 0);
71
   assert(height0 > 0);
72
   assert(depth0 > 0);
73
   if (target == PIPE_TEXTURE_CUBE)
74
      assert(layers == 6);
75
 
76
   DBG("%s target %d format %s last_level %d\n", __FUNCTION__,
77
       (int) target, util_format_name(format), last_level);
78
 
79
   assert(format);
80
   assert(screen->is_format_supported(screen, format, target, 0,
81
                                      PIPE_BIND_SAMPLER_VIEW));
82
 
83
   memset(&pt, 0, sizeof(pt));
84
   pt.target = target;
85
   pt.format = format;
86
   pt.last_level = last_level;
87
   pt.width0 = width0;
88
   pt.height0 = height0;
89
   pt.depth0 = depth0;
90
   pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : layers);
91
   pt.usage = PIPE_USAGE_DEFAULT;
92
   pt.bind = bind;
93
   pt.flags = 0;
94
   pt.nr_samples = nr_samples;
95
 
96
   newtex = screen->resource_create(screen, &pt);
97
 
98
   assert(!newtex || pipe_is_referenced(&newtex->reference));
99
 
100
   return newtex;
101
}
102
 
103
 
104
/**
105
 * In OpenGL the number of 1D array texture layers is the "height" and
106
 * the number of 2D array texture layers is the "depth".  In Gallium the
107
 * number of layers in an array texture is a separate 'array_size' field.
108
 * This function converts dimensions from the former to the later.
109
 */
110
void
111
st_gl_texture_dims_to_pipe_dims(GLenum texture,
112
                                GLuint widthIn,
113
                                GLuint heightIn,
114
                                GLuint depthIn,
115
                                GLuint *widthOut,
116
                                GLuint *heightOut,
117
                                GLuint *depthOut,
118
                                GLuint *layersOut)
119
{
120
   switch (texture) {
121
   case GL_TEXTURE_1D:
122
   case GL_PROXY_TEXTURE_1D:
123
      assert(heightIn == 1);
124
      assert(depthIn == 1);
125
      *widthOut = widthIn;
126
      *heightOut = 1;
127
      *depthOut = 1;
128
      *layersOut = 1;
129
      break;
130
   case GL_TEXTURE_1D_ARRAY:
131
   case GL_PROXY_TEXTURE_1D_ARRAY:
132
      assert(depthIn == 1);
133
      *widthOut = widthIn;
134
      *heightOut = 1;
135
      *depthOut = 1;
136
      *layersOut = heightIn;
137
      break;
138
   case GL_TEXTURE_2D:
139
   case GL_PROXY_TEXTURE_2D:
140
   case GL_TEXTURE_RECTANGLE:
141
   case GL_PROXY_TEXTURE_RECTANGLE:
142
   case GL_TEXTURE_EXTERNAL_OES:
143
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
144
   case GL_TEXTURE_2D_MULTISAMPLE:
145
      assert(depthIn == 1);
146
      *widthOut = widthIn;
147
      *heightOut = heightIn;
148
      *depthOut = 1;
149
      *layersOut = 1;
150
      break;
151
   case GL_TEXTURE_CUBE_MAP:
152
   case GL_PROXY_TEXTURE_CUBE_MAP:
153
   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
154
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
155
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
156
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
157
   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
158
   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
159
      assert(depthIn == 1);
160
      *widthOut = widthIn;
161
      *heightOut = heightIn;
162
      *depthOut = 1;
163
      *layersOut = 6;
164
      break;
165
   case GL_TEXTURE_2D_ARRAY:
166
   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
167
   case GL_PROXY_TEXTURE_2D_ARRAY:
168
   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
169
      *widthOut = widthIn;
170
      *heightOut = heightIn;
171
      *depthOut = 1;
172
      *layersOut = depthIn;
173
      break;
174
   case GL_TEXTURE_CUBE_MAP_ARRAY:
175
   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
176
      *widthOut = widthIn;
177
      *heightOut = heightIn;
178
      *depthOut = 1;
179
      *layersOut = depthIn;
180
      break;
181
   default:
182
      assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()");
183
      /* fall-through */
184
   case GL_TEXTURE_3D:
185
   case GL_PROXY_TEXTURE_3D:
186
      *widthOut = widthIn;
187
      *heightOut = heightIn;
188
      *depthOut = depthIn;
189
      *layersOut = 1;
190
      break;
191
   }
192
}
193
 
194
 
195
/**
196
 * Check if a texture image can be pulled into a unified mipmap texture.
197
 */
198
GLboolean
199
st_texture_match_image(const struct pipe_resource *pt,
200
                       const struct gl_texture_image *image)
201
{
202
   GLuint ptWidth, ptHeight, ptDepth, ptLayers;
203
 
204
   /* Images with borders are never pulled into mipmap textures.
205
    */
206
   if (image->Border)
207
      return GL_FALSE;
208
 
209
   /* Check if this image's format matches the established texture's format.
210
    */
211
   if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format)
212
      return GL_FALSE;
213
 
214
   st_gl_texture_dims_to_pipe_dims(image->TexObject->Target,
215
                                   image->Width, image->Height, image->Depth,
216
                                   &ptWidth, &ptHeight, &ptDepth, &ptLayers);
217
 
218
   /* Test if this image's size matches what's expected in the
219
    * established texture.
220
    */
221
   if (ptWidth != u_minify(pt->width0, image->Level) ||
222
       ptHeight != u_minify(pt->height0, image->Level) ||
223
       ptDepth != u_minify(pt->depth0, image->Level) ||
224
       ptLayers != pt->array_size)
225
      return GL_FALSE;
226
 
227
   return GL_TRUE;
228
}
229
 
230
 
231
/**
232
 * Map a texture image and return the address for a particular 2D face/slice/
233
 * layer.  The stImage indicates the cube face and mipmap level.  The slice
234
 * of the 3D texture is passed in 'zoffset'.
235
 * \param usage  one of the PIPE_TRANSFER_x values
236
 * \param x, y, w, h  the region of interest of the 2D image.
237
 * \return address of mapping or NULL if any error
238
 */
239
GLubyte *
240
st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
241
                     enum pipe_transfer_usage usage,
242
                     GLuint x, GLuint y, GLuint z,
243
                     GLuint w, GLuint h, GLuint d)
244
{
245
   struct st_texture_object *stObj =
246
      st_texture_object(stImage->base.TexObject);
247
   GLuint level;
248
 
249
   DBG("%s \n", __FUNCTION__);
250
 
251
   if (!stImage->pt)
252
      return NULL;
253
 
254
   if (stObj->pt != stImage->pt)
255
      level = 0;
256
   else
257
      level = stImage->base.Level;
258
 
259
   return pipe_transfer_map_3d(st->pipe, stImage->pt, level, usage,
260
                               x, y, z + stImage->base.Face,
261
                               w, h, d, &stImage->transfer);
262
}
263
 
264
 
265
void
266
st_texture_image_unmap(struct st_context *st,
267
                       struct st_texture_image *stImage)
268
{
269
   struct pipe_context *pipe = st->pipe;
270
 
271
   DBG("%s\n", __FUNCTION__);
272
 
273
   pipe_transfer_unmap(pipe, stImage->transfer);
274
   stImage->transfer = NULL;
275
}
276
 
277
 
278
/* Upload data for a particular image.
279
 */
280
void
281
st_texture_image_data(struct st_context *st,
282
                      struct pipe_resource *dst,
283
                      GLuint face,
284
                      GLuint level,
285
                      void *src,
286
                      GLuint src_row_stride, GLuint src_image_stride)
287
{
288
   struct pipe_context *pipe = st->pipe;
289
   GLuint i;
290
   const GLubyte *srcUB = src;
291
   GLuint layers;
292
 
293
   if (dst->target == PIPE_TEXTURE_1D_ARRAY ||
294
       dst->target == PIPE_TEXTURE_2D_ARRAY ||
295
       dst->target == PIPE_TEXTURE_CUBE_ARRAY)
296
      layers = dst->array_size;
297
   else
298
      layers = u_minify(dst->depth0, level);
299
 
300
   DBG("%s\n", __FUNCTION__);
301
 
302
   for (i = 0; i < layers; i++) {
303
      struct pipe_box box;
304
      u_box_2d_zslice(0, 0, face + i,
305
                      u_minify(dst->width0, level),
306
                      u_minify(dst->height0, level),
307
                      &box);
308
 
309
      pipe->transfer_inline_write(pipe, dst, level, PIPE_TRANSFER_WRITE,
310
                                  &box, srcUB, src_row_stride, 0);
311
 
312
      srcUB += src_image_stride;
313
   }
314
}
315
 
316
 
317
/**
318
 * For debug only: get/print center pixel in the src resource.
319
 */
320
static void
321
print_center_pixel(struct pipe_context *pipe, struct pipe_resource *src)
322
{
323
   struct pipe_transfer *xfer;
324
   struct pipe_box region;
325
   ubyte *map;
326
 
327
   region.x = src->width0 / 2;
328
   region.y = src->height0 / 2;
329
   region.z = 0;
330
   region.width = 1;
331
   region.height = 1;
332
   region.depth = 1;
333
 
334
   map = pipe->transfer_map(pipe, src, 0, PIPE_TRANSFER_READ, ®ion, &xfer);
335
 
336
   printf("center pixel: %d %d %d %d\n", map[0], map[1], map[2], map[3]);
337
 
338
   pipe->transfer_unmap(pipe, xfer);
339
}
340
 
341
 
342
/**
343
 * Copy the image at level=0 in 'src' to the 'dst' resource at 'dstLevel'.
344
 * This is used to copy mipmap images from one texture buffer to another.
345
 * This typically happens when our initial guess at the total texture size
346
 * is incorrect (see the guess_and_alloc_texture() function).
347
 */
348
void
349
st_texture_image_copy(struct pipe_context *pipe,
350
                      struct pipe_resource *dst, GLuint dstLevel,
351
                      struct pipe_resource *src, GLuint srcLevel,
352
                      GLuint face)
353
{
354
   GLuint width = u_minify(dst->width0, dstLevel);
355
   GLuint height = u_minify(dst->height0, dstLevel);
356
   GLuint depth = u_minify(dst->depth0, dstLevel);
357
   struct pipe_box src_box;
358
   GLuint i;
359
 
360
   if (u_minify(src->width0, srcLevel) != width ||
361
       u_minify(src->height0, srcLevel) != height ||
362
       u_minify(src->depth0, srcLevel) != depth) {
363
      /* The source image size doesn't match the destination image size.
364
       * This can happen in some degenerate situations such as rendering to a
365
       * cube map face which was set up with mismatched texture sizes.
366
       */
367
      return;
368
   }
369
 
370
   src_box.x = 0;
371
   src_box.y = 0;
372
   src_box.width = width;
373
   src_box.height = height;
374
   src_box.depth = 1;
375
   /* Loop over 3D image slices */
376
   /* could (and probably should) use "true" 3d box here -
377
      but drivers can't quite handle it yet */
378
   for (i = face; i < face + depth; i++) {
379
      src_box.z = i;
380
 
381
      if (0)  {
382
         print_center_pixel(pipe, src);
383
      }
384
 
385
      pipe->resource_copy_region(pipe,
386
                                 dst,
387
                                 dstLevel,
388
                                 0, 0, i,/* destX, Y, Z */
389
                                 src,
390
                                 srcLevel,
391
                                 &src_box);
392
   }
393
}
394
 
395
 
396
struct pipe_resource *
397
st_create_color_map_texture(struct gl_context *ctx)
398
{
399
   struct st_context *st = st_context(ctx);
400
   struct pipe_resource *pt;
401
   enum pipe_format format;
402
   const uint texSize = 256; /* simple, and usually perfect */
403
 
404
   /* find an RGBA texture format */
405
   format = st_choose_format(st, GL_RGBA, GL_NONE, GL_NONE,
406
                             PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW,
407
                             FALSE);
408
 
409
   /* create texture for color map/table */
410
   pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,
411
                          texSize, texSize, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
412
   return pt;
413
}
414