r300-gallium: Fix C99 error.
[mesa.git] / src / gallium / drivers / r300 / r300_texture.c
1 /*
2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23 #include "r300_texture.h"
24
25 static int minify(int i)
26 {
27 return MAX2(1, i >> 1);
28 }
29
30 static void r300_setup_miptree(struct r300_texture* tex)
31 {
32 struct pipe_texture* base = &tex->tex;
33 int stride, size, offset;
34 int i;
35
36 for (i = 0; i <= base->last_level; i++) {
37 if (i > 0) {
38 base->width[i] = minify(base->width[i-1]);
39 base->height[i] = minify(base->height[i-1]);
40 base->depth[i] = minify(base->depth[i-1]);
41 }
42
43 base->nblocksx[i] = pf_get_nblocksx(&base->block, base->width[i]);
44 base->nblocksy[i] = pf_get_nblocksy(&base->block, base->width[i]);
45
46 /* Radeons enjoy things in multiples of 32. */
47 /* XXX NPOT -> 64, not 32 */
48 stride = (base->nblocksx[i] * base->block.size + 63) & ~63;
49 size = stride * base->nblocksy[i] * base->depth[i];
50
51 /* XXX 64 for NPOT */
52 tex->offset[i] = (tex->size + 63) & ~63;
53 tex->size = tex->offset[i] + size;
54 }
55 }
56
57 /* Create a new texture. */
58 static struct pipe_texture*
59 r300_texture_create(struct pipe_screen* screen,
60 const struct pipe_texture* template)
61 {
62 /* XXX struct r300_screen* r300screen = r300_screen(screen); */
63
64 struct r300_texture* tex = CALLOC_STRUCT(r300_texture);
65
66 if (!tex) {
67 return NULL;
68 }
69
70 tex->tex = *template;
71 tex->tex.refcount = 1;
72 tex->tex.screen = screen;
73
74 r300_setup_miptree(tex);
75
76 tex->buffer = screen->buffer_create(screen, 64,
77 PIPE_BUFFER_USAGE_PIXEL,
78 tex->size);
79
80 if (!tex->buffer) {
81 FREE(tex);
82 return NULL;
83 }
84
85 return (struct pipe_texture*)tex;
86 }
87
88 static void r300_texture_release(struct pipe_screen* screen,
89 struct pipe_texture** texture)
90 {
91 if (!*texture) {
92 return;
93 }
94
95 (*texture)->refcount--;
96
97 if ((*texture)->refcount <= 0) {
98 struct r300_texture* tex = (struct r300_texture*)*texture;
99
100 pipe_buffer_reference(screen, &tex->buffer, NULL);
101
102 FREE(tex);
103 }
104
105 *texture = NULL;
106 }
107
108 static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
109 struct pipe_texture* texture,
110 unsigned face,
111 unsigned level,
112 unsigned zslice,
113 unsigned flags)
114 {
115 struct r300_texture* tex = (struct r300_texture*)texture;
116 struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface);
117 unsigned offset;
118
119 /* XXX this is certainly dependent on tex target */
120 offset = tex->offset[level];
121
122 if (surface) {
123 surface->refcount = 1;
124 pipe_texture_reference(&surface->texture, texture);
125 surface->format = texture->format;
126 surface->width = texture->width[level];
127 surface->height = texture->height[level];
128 surface->offset = offset;
129 surface->usage = flags;
130 surface->status = PIPE_SURFACE_STATUS_DEFINED;
131 }
132
133 return surface;
134 }
135
136 static void r300_tex_surface_release(struct pipe_screen* screen,
137 struct pipe_surface** surface)
138 {
139 struct pipe_surface* s = *surface;
140
141 s->refcount--;
142
143 if (s->refcount <= 0) {
144 pipe_texture_reference(&s->texture, NULL);
145 FREE(s);
146 }
147
148 *surface = NULL;
149 }
150
151 static struct pipe_texture*
152 r300_texture_blanket(struct pipe_screen* screen,
153 const struct pipe_texture* base,
154 const unsigned* stride,
155 struct pipe_buffer* buffer)
156 {
157 struct r300_texture* tex;
158
159 if (base->target != PIPE_TEXTURE_2D ||
160 base->last_level != 0 ||
161 base->depth[0] != 1) {
162 return NULL;
163 }
164
165 tex = CALLOC_STRUCT(r300_texture);
166 if (!tex) {
167 return NULL;
168 }
169
170 tex->tex = *base;
171 tex->tex.refcount = 1;
172 tex->tex.screen = screen;
173
174 tex->stride = *stride;
175
176 pipe_buffer_reference(screen, &tex->buffer, buffer);
177
178 return (struct pipe_texture*)tex;
179 }
180
181 void r300_init_screen_texture_functions(struct pipe_screen* screen)
182 {
183 screen->texture_create = r300_texture_create;
184 screen->texture_release = r300_texture_release;
185 screen->get_tex_surface = r300_get_tex_surface;
186 screen->tex_surface_release = r300_tex_surface_release;
187 screen->texture_blanket = r300_texture_blanket;
188 }