OSDN Git Service

st/xa: surfaces and sampler views are per context
[android-x86/external-mesa.git] / src / gallium / state_trackers / xa / xa_tracker.c
1 /**********************************************************
2  * Copyright 2009-2011 VMware, Inc. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  *
24  *********************************************************
25  * Authors:
26  * Thomas Hellstrom <thellstrom-at-vmware-dot-com>
27  */
28
29 #include "xa_tracker.h"
30 #include "xa_priv.h"
31 #include "pipe/p_state.h"
32 #include "pipe/p_format.h"
33 #include "state_tracker/drm_driver.h"
34 #include "util/u_inlines.h"
35
36 /*
37  * format_map [xa_surface_type][first..last in list].
38  * Needs to be updated when enum xa_formats is updated.
39  */
40
41 static const enum xa_formats preferred_a[] = { xa_format_a8 };
42
43 static const enum xa_formats preferred_argb[] =
44     { xa_format_a8r8g8b8, xa_format_x8r8g8b8, xa_format_r5g6b5,
45     xa_format_x1r5g5b5
46 };
47 static const enum xa_formats preferred_z[] =
48     { xa_format_z32, xa_format_z24, xa_format_z16 };
49 static const enum xa_formats preferred_sz[] =
50     { xa_format_x8z24, xa_format_s8z24 };
51 static const enum xa_formats preferred_zs[] =
52     { xa_format_z24x8, xa_format_z24s8 };
53 static const enum xa_formats preferred_yuv[] = { xa_format_yuv8 };
54
55 static const enum xa_formats *preferred[] =
56     { NULL, preferred_a, preferred_argb, NULL, NULL,
57     preferred_z, preferred_zs, preferred_sz, preferred_yuv
58 };
59
60 static const unsigned int num_preferred[] = { 0,
61     sizeof(preferred_a) / sizeof(enum xa_formats),
62     sizeof(preferred_argb) / sizeof(enum xa_formats),
63     0,
64     0,
65     sizeof(preferred_z) / sizeof(enum xa_formats),
66     sizeof(preferred_zs) / sizeof(enum xa_formats),
67     sizeof(preferred_sz) / sizeof(enum xa_formats),
68     sizeof(preferred_yuv) / sizeof(enum xa_formats)
69 };
70
71 static const unsigned int stype_bind[XA_LAST_SURFACE_TYPE] = { 0,
72     PIPE_BIND_SAMPLER_VIEW,
73     PIPE_BIND_SAMPLER_VIEW,
74     PIPE_BIND_SAMPLER_VIEW,
75     PIPE_BIND_SAMPLER_VIEW,
76     PIPE_BIND_DEPTH_STENCIL,
77     PIPE_BIND_DEPTH_STENCIL,
78     PIPE_BIND_DEPTH_STENCIL,
79     PIPE_BIND_SAMPLER_VIEW
80 };
81
82 static struct xa_format_descriptor
83 xa_get_pipe_format(enum xa_formats xa_format)
84 {
85     struct xa_format_descriptor fdesc;
86
87     fdesc.xa_format = xa_format;
88
89     switch (xa_format) {
90     case xa_format_a8r8g8b8:
91         fdesc.format = PIPE_FORMAT_B8G8R8A8_UNORM;
92         break;
93     case xa_format_x8r8g8b8:
94         fdesc.format = PIPE_FORMAT_B8G8R8X8_UNORM;
95         break;
96     case xa_format_r5g6b5:
97         fdesc.format = PIPE_FORMAT_B5G6R5_UNORM;
98         break;
99     case xa_format_x1r5g5b5:
100         fdesc.format = PIPE_FORMAT_B5G5R5A1_UNORM;
101         break;
102     case xa_format_a8:
103         fdesc.format = PIPE_FORMAT_L8_UNORM;
104         break;
105     case xa_format_z24:
106         fdesc.format = PIPE_FORMAT_Z24X8_UNORM;
107         break;
108     case xa_format_z16:
109         fdesc.format = PIPE_FORMAT_Z16_UNORM;
110         break;
111     case xa_format_z32:
112         fdesc.format = PIPE_FORMAT_Z32_UNORM;
113         break;
114     case xa_format_x8z24:
115         fdesc.format = PIPE_FORMAT_Z24X8_UNORM;
116         break;
117     case xa_format_z24x8:
118         fdesc.format = PIPE_FORMAT_X8Z24_UNORM;
119         break;
120     case xa_format_s8z24:
121         fdesc.format = PIPE_FORMAT_Z24_UNORM_S8_USCALED;
122         break;
123     case xa_format_z24s8:
124         fdesc.format = PIPE_FORMAT_S8_USCALED_Z24_UNORM;
125         break;
126     case xa_format_yuv8:
127         fdesc.format = PIPE_FORMAT_L8_UNORM;
128         break;
129     default:
130         fdesc.xa_format = xa_format_unknown;
131         break;
132     }
133     return fdesc;
134 }
135
136 struct xa_tracker *
137 xa_tracker_create(int drm_fd)
138 {
139     struct xa_tracker *xa = calloc(1, sizeof(struct xa_tracker));
140     enum xa_surface_type stype;
141     unsigned int num_formats;
142
143     if (!xa)
144         return NULL;
145
146     xa->screen = driver_descriptor.create_screen(drm_fd);
147     if (!xa->screen)
148         goto out_no_screen;
149
150     xa->default_ctx = xa_context_create(xa);
151     if (!xa->default_ctx)
152         goto out_no_pipe;
153
154     num_formats = 0;
155     for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype)
156         num_formats += num_preferred[stype];
157
158     num_formats += 1;
159     xa->supported_formats = calloc(num_formats, sizeof(*xa->supported_formats));
160     if (!xa->supported_formats)
161         goto out_sf_alloc_fail;
162
163     xa->supported_formats[0] = xa_format_unknown;
164     num_formats = 1;
165     memset(xa->format_map, 0, sizeof(xa->format_map));
166
167     for (stype = 0; stype < XA_LAST_SURFACE_TYPE; ++stype) {
168         unsigned int bind = stype_bind[stype];
169         enum xa_formats xa_format;
170         int i;
171
172         for (i = 0; i < num_preferred[stype]; ++i) {
173             xa_format = preferred[stype][i];
174
175             struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format);
176
177             if (xa->screen->is_format_supported(xa->screen, fdesc.format,
178                                                 PIPE_TEXTURE_2D, 0, bind)) {
179                 if (xa->format_map[stype][0] == 0)
180                     xa->format_map[stype][0] = num_formats;
181                 xa->format_map[stype][1] = num_formats;
182                 xa->supported_formats[num_formats++] = xa_format;
183             }
184         }
185     }
186     return xa;
187
188  out_sf_alloc_fail:
189     xa_context_destroy(xa->default_ctx);
190  out_no_pipe:
191     xa->screen->destroy(xa->screen);
192  out_no_screen:
193     free(xa);
194     return NULL;
195 }
196
197 void
198 xa_tracker_destroy(struct xa_tracker *xa)
199 {
200     free(xa->supported_formats);
201     xa_context_destroy(xa->default_ctx);
202     xa->screen->destroy(xa->screen);
203     free(xa);
204 }
205
206 static int
207 xa_flags_compat(unsigned int old_flags, unsigned int new_flags)
208 {
209     unsigned int flag_diff = (old_flags ^ new_flags);
210
211     if (flag_diff == 0)
212         return 1;
213
214     if (flag_diff & XA_FLAG_SHARED)
215         return 0;
216     /*
217      * Don't recreate if we're dropping the render target flag.
218      */
219     if (flag_diff & XA_FLAG_RENDER_TARGET)
220         return ((new_flags & XA_FLAG_RENDER_TARGET) == 0);
221
222     /*
223      * Always recreate for unknown / unimplemented flags.
224      */
225     return 0;
226 }
227
228 static struct xa_format_descriptor
229 xa_get_format_stype_depth(struct xa_tracker *xa,
230                           enum xa_surface_type stype, unsigned int depth)
231 {
232     unsigned int i;
233     struct xa_format_descriptor fdesc;
234     int found = 0;
235
236     for (i = xa->format_map[stype][0]; i <= xa->format_map[stype][1]; ++i) {
237         fdesc = xa_get_pipe_format(xa->supported_formats[i]);
238         if (fdesc.xa_format != xa_format_unknown &&
239             xa_format_depth(fdesc.xa_format) == depth) {
240             found = 1;
241             break;
242         }
243     }
244
245     if (!found)
246         fdesc.xa_format = xa_format_unknown;
247
248     return fdesc;
249 }
250
251 int
252 xa_format_check_supported(struct xa_tracker *xa,
253                           enum xa_formats xa_format, unsigned int flags)
254 {
255     struct xa_format_descriptor fdesc = xa_get_pipe_format(xa_format);
256     unsigned int bind;
257
258     if (fdesc.xa_format == xa_format_unknown)
259         return -XA_ERR_INVAL;
260
261     bind = stype_bind[xa_format_type(fdesc.xa_format)];
262     if (flags & XA_FLAG_SHARED)
263         bind |= PIPE_BIND_SHARED;
264     if (flags & XA_FLAG_RENDER_TARGET)
265         bind |= PIPE_BIND_RENDER_TARGET;
266
267     if (!xa->screen->is_format_supported(xa->screen, fdesc.format,
268                                          PIPE_TEXTURE_2D, 0, bind))
269         return -XA_ERR_INVAL;
270
271     return XA_ERR_NONE;
272 }
273
274 struct xa_surface *
275 xa_surface_create(struct xa_tracker *xa,
276                   int width,
277                   int height,
278                   int depth,
279                   enum xa_surface_type stype,
280                   enum xa_formats xa_format, unsigned int flags)
281 {
282     struct pipe_resource *template;
283     struct xa_surface *srf;
284     struct xa_format_descriptor fdesc;
285
286     if (xa_format == xa_format_unknown)
287         fdesc = xa_get_format_stype_depth(xa, stype, depth);
288     else
289         fdesc = xa_get_pipe_format(xa_format);
290
291     if (fdesc.xa_format == xa_format_unknown)
292         return NULL;
293
294     srf = calloc(1, sizeof(*srf));
295     if (!srf)
296         return NULL;
297
298     template = &srf->template;
299     template->format = fdesc.format;
300     template->target = PIPE_TEXTURE_2D;
301     template->width0 = width;
302     template->height0 = height;
303     template->depth0 = 1;
304     template->array_size = 1;
305     template->last_level = 0;
306     template->bind = stype_bind[xa_format_type(fdesc.xa_format)];
307
308     if (flags & XA_FLAG_SHARED)
309         template->bind |= PIPE_BIND_SHARED;
310     if (flags & XA_FLAG_RENDER_TARGET)
311         template->bind |= PIPE_BIND_RENDER_TARGET;
312
313     srf->tex = xa->screen->resource_create(xa->screen, template);
314     if (!srf->tex)
315         goto out_no_tex;
316
317     srf->xa = xa;
318     srf->flags = flags;
319     srf->fdesc = fdesc;
320
321     return srf;
322  out_no_tex:
323     free(srf);
324     return NULL;
325 }
326
327 int
328 xa_surface_redefine(struct xa_surface *srf,
329                     int width,
330                     int height,
331                     int depth,
332                     enum xa_surface_type stype,
333                     enum xa_formats xa_format,
334                     unsigned int new_flags,
335                     int copy_contents)
336 {
337     struct pipe_resource *template = &srf->template;
338     struct pipe_resource *texture;
339     struct pipe_box src_box;
340     struct xa_tracker *xa = srf->xa;
341     int save_width;
342     int save_height;
343     unsigned int save_format;
344     struct xa_format_descriptor fdesc;
345
346
347     if (xa_format == xa_format_unknown)
348         fdesc = xa_get_format_stype_depth(xa, stype, depth);
349     else
350         fdesc = xa_get_pipe_format(xa_format);
351
352     if (width == template->width0 && height == template->height0 &&
353         template->format == fdesc.format &&
354         xa_flags_compat(srf->flags, new_flags))
355         return XA_ERR_NONE;
356
357     template->bind = stype_bind[xa_format_type(fdesc.xa_format)];
358     if (new_flags & XA_FLAG_SHARED)
359         template->bind |= PIPE_BIND_SHARED;
360     if (new_flags & XA_FLAG_RENDER_TARGET)
361         template->bind |= PIPE_BIND_RENDER_TARGET;
362
363     if (copy_contents) {
364         if (!xa_format_type_is_color(fdesc.xa_format) ||
365             xa_format_type(fdesc.xa_format) == xa_type_a)
366             return -XA_ERR_INVAL;
367
368         if (!xa->screen->is_format_supported(xa->screen, fdesc.format,
369                                              PIPE_TEXTURE_2D, 0,
370                                              template->bind |
371                                              PIPE_BIND_RENDER_TARGET))
372             return -XA_ERR_INVAL;
373     }
374
375     save_width = template->width0;
376     save_height = template->height0;
377     save_format = template->format;
378
379     template->width0 = width;
380     template->height0 = height;
381     template->format = fdesc.format;
382
383     texture = xa->screen->resource_create(xa->screen, template);
384     if (!texture) {
385         template->width0 = save_width;
386         template->height0 = save_height;
387         template->format = save_format;
388         return -XA_ERR_NORES;
389     }
390
391     if (copy_contents) {
392         struct pipe_context *pipe = xa->default_ctx->pipe;
393
394         u_box_origin_2d(xa_min(save_width, template->width0),
395                         xa_min(save_height, template->height0), &src_box);
396         pipe->resource_copy_region(pipe, texture,
397                                    0, 0, 0, 0, srf->tex, 0, &src_box);
398         pipe->flush(pipe, &xa->default_ctx->last_fence);
399     }
400
401     pipe_resource_reference(&srf->tex, texture);
402     pipe_resource_reference(&texture, NULL);
403     srf->fdesc = fdesc;
404     srf->flags = new_flags;
405
406     return XA_ERR_NONE;
407 }
408
409 void
410 xa_surface_destroy(struct xa_surface *srf)
411 {
412     pipe_resource_reference(&srf->tex, NULL);
413     free(srf);
414 }
415
416 extern void
417 xa_tracker_version(int *major, int *minor, int *patch)
418 {
419     *major = XA_TRACKER_VERSION_MAJOR;
420     *minor = XA_TRACKER_VERSION_MINOR;
421     *patch = XA_TRACKER_VERSION_PATCH;
422 }
423
424 extern int
425 xa_surface_handle(struct xa_surface *srf,
426                   uint32_t * handle, unsigned int *stride)
427 {
428     struct winsys_handle whandle;
429
430     struct pipe_screen *screen = srf->xa->screen;
431     boolean res;
432
433     memset(&whandle, 0, sizeof(whandle));
434     whandle.type = DRM_API_HANDLE_TYPE_SHARED;
435     res = screen->resource_get_handle(screen, srf->tex, &whandle);
436     if (!res)
437         return -XA_ERR_INVAL;
438
439     *handle = whandle.handle;
440     *stride = whandle.stride;
441
442     return XA_ERR_NONE;
443 }
444
445 enum xa_formats
446 xa_surface_format(const struct xa_surface *srf)
447 {
448     return srf->fdesc.xa_format;
449 }