llvmpipe: Remove unnecessary headers.
[mesa.git] / src / gallium / drivers / llvmpipe / lp_texture.c
1 /**************************************************************************
2 *
3 * Copyright 2006 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 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Michel Dänzer <michel@tungstengraphics.com>
31 */
32
33 #include "pipe/p_context.h"
34 #include "pipe/p_defines.h"
35 #include "pipe/p_inlines.h"
36 #include "util/u_math.h"
37 #include "util/u_memory.h"
38
39 #include "lp_context.h"
40 #include "lp_state.h"
41 #include "lp_texture.h"
42 #include "lp_screen.h"
43 #include "lp_winsys.h"
44
45
46 /* Simple, maximally packed layout.
47 */
48
49
50 /* Conventional allocation path for non-display textures:
51 */
52 static boolean
53 llvmpipe_texture_layout(struct llvmpipe_screen *screen,
54 struct llvmpipe_texture * lpt)
55 {
56 struct pipe_texture *pt = &lpt->base;
57 unsigned level;
58 unsigned width = pt->width[0];
59 unsigned height = pt->height[0];
60 unsigned depth = pt->depth[0];
61
62 unsigned buffer_size = 0;
63
64 pf_get_block(lpt->base.format, &lpt->base.block);
65
66 for (level = 0; level <= pt->last_level; level++) {
67 unsigned nblocksx, nblocksy;
68
69 pt->width[level] = width;
70 pt->height[level] = height;
71 pt->depth[level] = depth;
72 pt->nblocksx[level] = pf_get_nblocksx(&pt->block, width);
73 pt->nblocksy[level] = pf_get_nblocksy(&pt->block, height);
74
75 /* Allocate storage for whole quads. This is particularly important
76 * for depth surfaces, which are currently stored in a swizzled format. */
77 nblocksx = pf_get_nblocksx(&pt->block, align(width, 2));
78 nblocksy = pf_get_nblocksy(&pt->block, align(height, 2));
79
80 lpt->stride[level] = align(nblocksx*pt->block.size, 16);
81
82 lpt->level_offset[level] = buffer_size;
83
84 buffer_size += (nblocksy *
85 ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
86 lpt->stride[level]);
87
88 width = minify(width);
89 height = minify(height);
90 depth = minify(depth);
91 }
92
93 lpt->data = align_malloc(buffer_size, 16);
94
95 return lpt->data != NULL;
96 }
97
98 static boolean
99 llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
100 struct llvmpipe_texture * lpt)
101 {
102 struct llvmpipe_winsys *winsys = screen->winsys;
103
104 pf_get_block(lpt->base.format, &lpt->base.block);
105 lpt->base.nblocksx[0] = pf_get_nblocksx(&lpt->base.block, lpt->base.width[0]);
106 lpt->base.nblocksy[0] = pf_get_nblocksy(&lpt->base.block, lpt->base.height[0]);
107
108 lpt->dt = winsys->displaytarget_create(winsys,
109 lpt->base.format,
110 lpt->base.width[0],
111 lpt->base.height[0],
112 16,
113 &lpt->stride[0] );
114
115 return lpt->dt != NULL;
116 }
117
118
119
120
121
122 static struct pipe_texture *
123 llvmpipe_texture_create(struct pipe_screen *_screen,
124 const struct pipe_texture *templat)
125 {
126 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
127 struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture);
128 if (!lpt)
129 return NULL;
130
131 lpt->base = *templat;
132 pipe_reference_init(&lpt->base.reference, 1);
133 lpt->base.screen = &screen->base;
134
135 /* XXX: The xlib state tracker is brain-dead and will request
136 * PIPE_FORMAT_Z16_UNORM no matter how much we tell it we don't support it.
137 */
138 if(lpt->base.format == PIPE_FORMAT_Z16_UNORM)
139 lpt->base.format = PIPE_FORMAT_Z32_UNORM;
140
141 if (lpt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
142 PIPE_TEXTURE_USAGE_PRIMARY)) {
143 if (!llvmpipe_displaytarget_layout(screen, lpt))
144 goto fail;
145 }
146 else {
147 if (!llvmpipe_texture_layout(screen, lpt))
148 goto fail;
149 }
150
151 return &lpt->base;
152
153 fail:
154 FREE(lpt);
155 return NULL;
156 }
157
158
159 static struct pipe_texture *
160 llvmpipe_texture_blanket(struct pipe_screen * screen,
161 const struct pipe_texture *base,
162 const unsigned *stride,
163 struct pipe_buffer *buffer)
164 {
165 /* FIXME */
166 #if 0
167 struct llvmpipe_texture *lpt;
168 assert(screen);
169
170 /* Only supports one type */
171 if (base->target != PIPE_TEXTURE_2D ||
172 base->last_level != 0 ||
173 base->depth[0] != 1) {
174 return NULL;
175 }
176
177 lpt = CALLOC_STRUCT(llvmpipe_texture);
178 if (!lpt)
179 return NULL;
180
181 lpt->base = *base;
182 pipe_reference_init(&lpt->base.reference, 1);
183 lpt->base.screen = screen;
184 lpt->base.nblocksx[0] = pf_get_nblocksx(&lpt->base.block, lpt->base.width[0]);
185 lpt->base.nblocksy[0] = pf_get_nblocksy(&lpt->base.block, lpt->base.height[0]);
186 lpt->stride[0] = stride[0];
187
188 pipe_buffer_reference(&lpt->buffer, buffer);
189
190 return &lpt->base;
191 #else
192 return NULL;
193 #endif
194 }
195
196
197 static void
198 llvmpipe_texture_destroy(struct pipe_texture *pt)
199 {
200 struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen);
201 struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
202
203 if(lpt->dt) {
204 struct llvmpipe_winsys *winsys = screen->winsys;
205 winsys->displaytarget_destroy(winsys, lpt->dt);
206 }
207 else
208 align_free(lpt->data);
209
210 FREE(lpt);
211 }
212
213
214 static struct pipe_surface *
215 llvmpipe_get_tex_surface(struct pipe_screen *screen,
216 struct pipe_texture *pt,
217 unsigned face, unsigned level, unsigned zslice,
218 unsigned usage)
219 {
220 struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
221 struct pipe_surface *ps;
222
223 assert(level <= pt->last_level);
224
225 ps = CALLOC_STRUCT(pipe_surface);
226 if (ps) {
227 pipe_reference_init(&ps->reference, 1);
228 pipe_texture_reference(&ps->texture, pt);
229 ps->format = pt->format;
230 ps->width = pt->width[level];
231 ps->height = pt->height[level];
232 ps->offset = lpt->level_offset[level];
233 ps->usage = usage;
234
235 /* Because we are llvmpipe, anything that the state tracker
236 * thought was going to be done with the GPU will actually get
237 * done with the CPU. Let's adjust the flags to take that into
238 * account.
239 */
240 if (ps->usage & PIPE_BUFFER_USAGE_GPU_WRITE) {
241 /* GPU_WRITE means "render" and that can involve reads (blending) */
242 ps->usage |= PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_CPU_READ;
243 }
244
245 if (ps->usage & PIPE_BUFFER_USAGE_GPU_READ)
246 ps->usage |= PIPE_BUFFER_USAGE_CPU_READ;
247
248 if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE |
249 PIPE_BUFFER_USAGE_GPU_WRITE)) {
250 /* Mark the surface as dirty. The tile cache will look for this. */
251 lpt->timestamp++;
252 llvmpipe_screen(screen)->timestamp++;
253 }
254
255 ps->face = face;
256 ps->level = level;
257 ps->zslice = zslice;
258
259 if (pt->target == PIPE_TEXTURE_CUBE) {
260 ps->offset += face * pt->nblocksy[level] * lpt->stride[level];
261 }
262 else if (pt->target == PIPE_TEXTURE_3D) {
263 ps->offset += zslice * pt->nblocksy[level] * lpt->stride[level];
264 }
265 else {
266 assert(face == 0);
267 assert(zslice == 0);
268 }
269 }
270 return ps;
271 }
272
273
274 static void
275 llvmpipe_tex_surface_destroy(struct pipe_surface *surf)
276 {
277 /* Effectively do the texture_update work here - if texture images
278 * needed post-processing to put them into hardware layout, this is
279 * where it would happen. For llvmpipe, nothing to do.
280 */
281 assert(surf->texture);
282 pipe_texture_reference(&surf->texture, NULL);
283 FREE(surf);
284 }
285
286
287 static struct pipe_transfer *
288 llvmpipe_get_tex_transfer(struct pipe_screen *screen,
289 struct pipe_texture *texture,
290 unsigned face, unsigned level, unsigned zslice,
291 enum pipe_transfer_usage usage,
292 unsigned x, unsigned y, unsigned w, unsigned h)
293 {
294 struct llvmpipe_texture *lptex = llvmpipe_texture(texture);
295 struct llvmpipe_transfer *lpt;
296
297 assert(texture);
298 assert(level <= texture->last_level);
299
300 lpt = CALLOC_STRUCT(llvmpipe_transfer);
301 if (lpt) {
302 struct pipe_transfer *pt = &lpt->base;
303 pipe_texture_reference(&pt->texture, texture);
304 pt->format = texture->format;
305 pt->block = texture->block;
306 pt->x = x;
307 pt->y = y;
308 pt->width = w;
309 pt->height = h;
310 pt->nblocksx = texture->nblocksx[level];
311 pt->nblocksy = texture->nblocksy[level];
312 pt->stride = lptex->stride[level];
313 pt->usage = usage;
314 pt->face = face;
315 pt->level = level;
316 pt->zslice = zslice;
317
318 lpt->offset = lptex->level_offset[level];
319
320 if (texture->target == PIPE_TEXTURE_CUBE) {
321 lpt->offset += face * pt->nblocksy * pt->stride;
322 }
323 else if (texture->target == PIPE_TEXTURE_3D) {
324 lpt->offset += zslice * pt->nblocksy * pt->stride;
325 }
326 else {
327 assert(face == 0);
328 assert(zslice == 0);
329 }
330 return pt;
331 }
332 return NULL;
333 }
334
335
336 static void
337 llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer)
338 {
339 /* Effectively do the texture_update work here - if texture images
340 * needed post-processing to put them into hardware layout, this is
341 * where it would happen. For llvmpipe, nothing to do.
342 */
343 assert (transfer->texture);
344 pipe_texture_reference(&transfer->texture, NULL);
345 FREE(transfer);
346 }
347
348
349 static void *
350 llvmpipe_transfer_map( struct pipe_screen *_screen,
351 struct pipe_transfer *transfer )
352 {
353 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
354 ubyte *map, *xfer_map;
355 struct llvmpipe_texture *lpt;
356
357 assert(transfer->texture);
358 lpt = llvmpipe_texture(transfer->texture);
359
360 if(lpt->dt) {
361 struct llvmpipe_winsys *winsys = screen->winsys;
362
363 map = winsys->displaytarget_map(winsys, lpt->dt,
364 pipe_transfer_buffer_flags(transfer));
365 if (map == NULL)
366 return NULL;
367 }
368 else
369 map = lpt->data;
370
371 /* May want to different things here depending on read/write nature
372 * of the map:
373 */
374 if (transfer->texture && (transfer->usage & PIPE_TRANSFER_WRITE))
375 {
376 /* Do something to notify sharing contexts of a texture change.
377 * In llvmpipe, that would mean flushing the texture cache.
378 */
379 screen->timestamp++;
380 }
381
382 xfer_map = map + llvmpipe_transfer(transfer)->offset +
383 transfer->y / transfer->block.height * transfer->stride +
384 transfer->x / transfer->block.width * transfer->block.size;
385 /*printf("map = %p xfer map = %p\n", map, xfer_map);*/
386 return xfer_map;
387 }
388
389
390 static void
391 llvmpipe_transfer_unmap(struct pipe_screen *_screen,
392 struct pipe_transfer *transfer)
393 {
394 struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
395 struct llvmpipe_texture *lpt;
396
397 assert(transfer->texture);
398 lpt = llvmpipe_texture(transfer->texture);
399
400 if(lpt->dt) {
401 struct llvmpipe_winsys *winsys = screen->winsys;
402 winsys->displaytarget_unmap(winsys, lpt->dt);
403 }
404 }
405
406
407 void
408 llvmpipe_init_texture_funcs(struct llvmpipe_context *lp)
409 {
410 }
411
412
413 void
414 llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen)
415 {
416 screen->texture_create = llvmpipe_texture_create;
417 screen->texture_blanket = llvmpipe_texture_blanket;
418 screen->texture_destroy = llvmpipe_texture_destroy;
419
420 screen->get_tex_surface = llvmpipe_get_tex_surface;
421 screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;
422
423 screen->get_tex_transfer = llvmpipe_get_tex_transfer;
424 screen->tex_transfer_destroy = llvmpipe_tex_transfer_destroy;
425 screen->transfer_map = llvmpipe_transfer_map;
426 screen->transfer_unmap = llvmpipe_transfer_unmap;
427 }