st_texture.c revision b859cdf6f191b4d8b56537c8dc30082a7e2d94b3
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 "st_context.h"
29#include "st_format.h"
30#include "st_texture.h"
31#include "enums.h"
32
33#include "pipe/p_state.h"
34#include "pipe/p_context.h"
35#include "pipe/p_defines.h"
36#include "pipe/p_inlines.h"
37#include "pipe/p_util.h"
38#include "pipe/p_inlines.h"
39#include "pipe/p_winsys.h"
40
41
42#define DBG if(0) printf
43
44#if 0
45static GLenum
46target_to_target(GLenum target)
47{
48   switch (target) {
49   case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
50   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
51   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
52   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
53   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
54   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
55      return GL_TEXTURE_CUBE_MAP_ARB;
56   default:
57      return target;
58   }
59}
60#endif
61
62struct pipe_texture *
63st_texture_create(struct st_context *st,
64                  unsigned target,
65		  unsigned format,
66		  GLenum internal_format,
67		  GLuint first_level,
68		  GLuint last_level,
69		  GLuint width0,
70		  GLuint height0,
71		  GLuint depth0,
72		  GLuint compress_byte)
73{
74   struct pipe_texture *pt = CALLOC_STRUCT(pipe_texture);
75
76   assert(target <= PIPE_TEXTURE_CUBE);
77
78   DBG("%s target %s format %s level %d..%d\n", __FUNCTION__,
79       _mesa_lookup_enum_by_nr(target),
80       _mesa_lookup_enum_by_nr(internal_format), first_level, last_level);
81
82   if (!pt)
83      return NULL;
84
85   assert(format);
86
87   pt->target = target;
88   pt->format = format;
89   pt->internal_format = internal_format;
90   pt->first_level = first_level;
91   pt->last_level = last_level;
92   pt->width[0] = width0;
93   pt->height[0] = height0;
94   pt->depth[0] = depth0;
95   pt->compressed = compress_byte ? 1 : 0;
96   pt->cpp = pt->compressed ? compress_byte : st_sizeof_format(format);
97   pt->refcount = 1;
98
99   st->pipe->texture_create(st->pipe, &pt);
100
101   return pt;
102}
103
104
105
106
107/* Can the image be pulled into a unified mipmap texture.  This mirrors
108 * the completeness test in a lot of ways.
109 *
110 * Not sure whether I want to pass gl_texture_image here.
111 */
112GLboolean
113st_texture_match_image(struct pipe_texture *pt,
114                          struct gl_texture_image *image,
115                          GLuint face, GLuint level)
116{
117   /* Images with borders are never pulled into mipmap textures.
118    */
119   if (image->Border)
120      return GL_FALSE;
121
122   if (image->InternalFormat != pt->internal_format ||
123       image->IsCompressed != pt->compressed)
124      return GL_FALSE;
125
126   /* Test image dimensions against the base level image adjusted for
127    * minification.  This will also catch images not present in the
128    * texture, changed targets, etc.
129    */
130   if (image->Width != pt->width[level] ||
131       image->Height != pt->height[level] ||
132       image->Depth != pt->depth[level])
133      return GL_FALSE;
134
135   return GL_TRUE;
136}
137
138
139#if 000
140/* Although we use the image_offset[] array to store relative offsets
141 * to cube faces, Mesa doesn't know anything about this and expects
142 * each cube face to be treated as a separate image.
143 *
144 * These functions present that view to mesa:
145 */
146const GLuint *
147st_texture_depth_offsets(struct pipe_texture *pt, GLuint level)
148{
149   static const GLuint zero = 0;
150
151   if (pt->target != PIPE_TEXTURE_3D || pt->level[level].nr_images == 1)
152      return &zero;
153   else
154      return pt->level[level].image_offset;
155}
156
157
158/**
159 * Return the offset to the given mipmap texture image within the
160 * texture memory buffer, in bytes.
161 */
162GLuint
163st_texture_image_offset(const struct pipe_texture * pt,
164                        GLuint face, GLuint level)
165{
166   if (pt->target == PIPE_TEXTURE_CUBE)
167      return (pt->level[level].level_offset +
168              pt->level[level].image_offset[face] * pt->cpp);
169   else
170      return pt->level[level].level_offset;
171}
172#endif
173
174
175/**
176 * Map a teximage in a mipmap texture.
177 * \param row_stride  returns row stride in bytes
178 * \param image_stride  returns image stride in bytes (for 3D textures).
179 * \return address of mapping
180 */
181GLubyte *
182st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
183		     GLuint zoffset)
184{
185   struct pipe_texture *pt = stImage->pt;
186   DBG("%s \n", __FUNCTION__);
187
188   stImage->surface = st->pipe->get_tex_surface(st->pipe, pt, stImage->face,
189						stImage->level,	zoffset);
190
191   return pipe_surface_map(stImage->surface);
192}
193
194void
195st_texture_image_unmap(struct st_texture_image *stImage)
196{
197   DBG("%s\n", __FUNCTION__);
198
199   pipe_surface_unmap(stImage->surface);
200
201   pipe_surface_reference(&stImage->surface, NULL);
202}
203
204
205
206/* Upload data for a particular image.
207 */
208void
209st_texture_image_data(struct pipe_context *pipe,
210                      struct pipe_texture *dst,
211                      GLuint face,
212                      GLuint level,
213                      void *src,
214                      GLuint src_row_pitch, GLuint src_image_pitch)
215{
216   GLuint depth = dst->depth[level];
217   GLuint i;
218   GLuint height = 0;
219   const GLubyte *srcUB = src;
220   struct pipe_surface *dst_surface;
221
222   DBG("%s\n", __FUNCTION__);
223   for (i = 0; i < depth; i++) {
224      height = dst->height[level];
225      if(dst->compressed)
226	 height /= 4;
227
228      dst_surface = pipe->get_tex_surface(pipe, dst, face, level, i);
229
230      pipe->surface_data(pipe, dst_surface,
231			 0, 0,                             /* dstx, dsty */
232			 srcUB,
233			 src_row_pitch,
234			 0, 0,                             /* source x, y */
235			 dst->width[level], height); /* width, height */
236
237      pipe_surface_reference(&dst_surface, NULL);
238
239      srcUB += src_image_pitch * dst->cpp;
240   }
241}
242
243/* Copy mipmap image between textures
244 */
245void
246st_texture_image_copy(struct pipe_context *pipe,
247                         struct pipe_texture *dst,
248                         GLuint face, GLuint level,
249                         struct pipe_texture *src)
250{
251   GLuint width = src->width[level];
252   GLuint height = src->height[level];
253   GLuint depth = src->depth[level];
254   struct pipe_surface *src_surface;
255   struct pipe_surface *dst_surface;
256   GLuint i;
257
258   if (dst->compressed)
259      height /= 4;
260   for (i = 0; i < depth; i++) {
261      dst_surface = pipe->get_tex_surface(pipe, dst, face, level, i);
262      src_surface = pipe->get_tex_surface(pipe, src, face, level, i);
263
264      pipe->surface_copy(pipe,
265			 dst_surface,
266			 0, 0, /* destX, Y */
267			 src_surface,
268			 0, 0, /* srcX, Y */
269			 width, height);
270
271      pipe_surface_reference(&dst_surface, NULL);
272      pipe_surface_reference(&src_surface, NULL);
273   }
274
275}
276