r600g: adapt to latest interfaces changes
[mesa.git] / src / gallium / drivers / r600 / r600_texture.c
1 /*
2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
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 * Authors:
24 * Jerome Glisse
25 * Corbin Simpson
26 */
27 #include <pipe/p_screen.h>
28 #include <util/u_format.h>
29 #include <util/u_math.h>
30 #include <util/u_inlines.h>
31 #include <util/u_memory.h>
32 #include "state_tracker/drm_api.h"
33 #include "r600_screen.h"
34 #include "r600_texture.h"
35
36 extern struct u_resource_vtbl r600_texture_vtbl;
37
38 unsigned long r600_texture_get_offset(struct r600_texture *rtex, unsigned level, unsigned zslice, unsigned face)
39 {
40 unsigned long offset = rtex->offset[level];
41
42 switch (rtex->b.b.target) {
43 case PIPE_TEXTURE_3D:
44 assert(face == 0);
45 return offset + zslice * rtex->layer_size[level];
46 case PIPE_TEXTURE_CUBE:
47 assert(zslice == 0);
48 return offset + face * rtex->layer_size[level];
49 default:
50 assert(zslice == 0 && face == 0);
51 return offset;
52 }
53 }
54
55 static void r600_setup_miptree(struct r600_screen *rscreen, struct r600_texture *rtex)
56 {
57 struct pipe_resource *ptex = &rtex->b.b;
58 unsigned long w, h, stride, size, layer_size, i, offset;
59
60 for (i = 0, offset = 0; i <= ptex->last_level; i++) {
61 w = u_minify(ptex->width0, i);
62 h = u_minify(ptex->height0, i);
63 stride = align(util_format_get_stride(ptex->format, w), 32);
64 layer_size = stride * h;
65 if (ptex->target == PIPE_TEXTURE_CUBE)
66 size = layer_size * 6;
67 else
68 size = layer_size * u_minify(ptex->depth0, i);
69 rtex->offset[i] = offset;
70 rtex->layer_size[i] = layer_size;
71 rtex->pitch[i] = stride / util_format_get_blocksize(ptex->format);
72 rtex->stride[i] = stride;
73 offset += align(size, 32);
74 }
75 rtex->size = offset;
76 }
77
78 struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
79 const struct pipe_resource *templ)
80 {
81 struct r600_texture *rtex = CALLOC_STRUCT(r600_texture);
82 struct r600_screen *rscreen = r600_screen(screen);
83 struct pipe_resource templ_buf;
84
85 if (!rtex) {
86 return NULL;
87 }
88 rtex->b.b = *templ;
89 rtex->b.vtbl = &r600_texture_vtbl;
90 pipe_reference_init(&rtex->b.b.reference, 1);
91 rtex->b.b.screen = screen;
92 r600_setup_miptree(rscreen, rtex);
93
94 memset(&templ_buf, 0, sizeof(struct pipe_resource));
95 templ_buf.target = PIPE_BUFFER;
96 templ_buf.format = PIPE_FORMAT_R8_UNORM;
97 templ_buf.usage = templ->usage;
98 templ_buf.bind = templ->bind;
99 templ_buf.width0 = rtex->size;
100 templ_buf.height0 = 1;
101 templ_buf.depth0 = 1;
102
103 rtex->buffer = screen->resource_create(screen, &templ_buf);
104 if (!rtex->buffer) {
105 FREE(rtex);
106 return NULL;
107 }
108 return &rtex->b.b;
109 }
110
111 static void r600_texture_destroy(struct pipe_screen *screen,
112 struct pipe_resource *ptex)
113 {
114 struct r600_texture *rtex = (struct r600_texture*)ptex;
115
116 pipe_resource_reference((struct pipe_resource**)&rtex, NULL);
117 FREE(rtex);
118 }
119
120 static struct pipe_surface *r600_get_tex_surface(struct pipe_screen *screen,
121 struct pipe_resource *texture,
122 unsigned face, unsigned level,
123 unsigned zslice, unsigned flags)
124 {
125 struct r600_texture *rtex = (struct r600_texture*)texture;
126 struct pipe_surface *surface = CALLOC_STRUCT(pipe_surface);
127 unsigned long offset;
128
129 if (surface == NULL)
130 return NULL;
131 offset = r600_texture_get_offset(rtex, level, zslice, face);
132 pipe_reference_init(&surface->reference, 1);
133 pipe_resource_reference(&surface->texture, texture);
134 surface->format = texture->format;
135 surface->width = u_minify(texture->width0, level);
136 surface->height = u_minify(texture->height0, level);
137 surface->offset = offset;
138 surface->usage = flags;
139 surface->zslice = zslice;
140 surface->texture = texture;
141 surface->face = face;
142 surface->level = level;
143 return surface;
144 }
145
146 static void r600_tex_surface_destroy(struct pipe_surface *surface)
147 {
148 pipe_resource_reference(&surface->texture, NULL);
149 FREE(surface);
150 }
151
152 struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen,
153 const struct pipe_resource *base,
154 struct winsys_handle *whandle)
155 {
156 struct pipe_resource *buffer;
157 struct r600_texture *rtex;
158
159 buffer = r600_buffer_from_handle(screen, whandle);
160 if (buffer == NULL) {
161 return NULL;
162 }
163
164 /* Support only 2D textures without mipmaps */
165 if (base->target != PIPE_TEXTURE_2D || base->depth0 != 1 || base->last_level != 0)
166 return NULL;
167
168 rtex = CALLOC_STRUCT(r600_texture);
169 if (rtex == NULL)
170 return NULL;
171
172 /* one ref already taken */
173 rtex->buffer = buffer;
174
175 rtex->b.b = *base;
176 rtex->b.vtbl = &r600_texture_vtbl;
177 pipe_reference_init(&rtex->b.b.reference, 1);
178 rtex->b.b.screen = screen;
179 rtex->stride_override = whandle->stride;
180 rtex->pitch[0] = whandle->stride / util_format_get_blocksize(base->format);
181 rtex->stride[0] = whandle->stride;
182 rtex->offset[0] = 0;
183 rtex->size = align(rtex->stride[0] * base->height0, 32);
184
185 return &rtex->b.b;
186 }
187
188 static boolean r600_texture_get_handle(struct pipe_screen* screen,
189 struct pipe_resource *texture,
190 struct winsys_handle *whandle)
191 {
192 struct r600_screen *rscreen = r600_screen(screen);
193 struct r600_texture* rtex = (struct r600_texture*)texture;
194
195 if (!rtex) {
196 return FALSE;
197 }
198
199 whandle->stride = rtex->stride[0];
200
201 r600_buffer_get_handle(rscreen->rw, rtex->buffer, whandle);
202
203 return TRUE;
204 }
205
206 static unsigned int r600_texture_is_referenced(struct pipe_context *context,
207 struct pipe_resource *texture,
208 unsigned face, unsigned level)
209 {
210 struct r600_texture *rtex = (struct r600_texture*)texture;
211
212 return r600_buffer_is_referenced_by_cs(context, rtex->buffer, face, level);
213 }
214
215 struct u_resource_vtbl r600_texture_vtbl =
216 {
217 r600_texture_get_handle, /* get_handle */
218 r600_texture_destroy, /* resource_destroy */
219 r600_texture_is_referenced, /* is_resource_referenced */
220 r600_texture_get_transfer, /* get_transfer */
221 r600_texture_transfer_destroy, /* transfer_destroy */
222 r600_texture_transfer_map, /* transfer_map */
223 u_default_transfer_flush_region,/* transfer_flush_region */
224 r600_texture_transfer_unmap, /* transfer_unmap */
225 u_default_transfer_inline_write /* transfer_inline_write */
226 };
227
228 void r600_init_screen_texture_functions(struct pipe_screen *screen)
229 {
230 screen->get_tex_surface = r600_get_tex_surface;
231 screen->tex_surface_destroy = r600_tex_surface_destroy;
232 }