1 /**************************************************************************
2  *
3  * Copyright 2010 VMware, Inc.
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 VMWARE 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 
29 #include "pipe/p_screen.h"
30 #include "pipe/p_state.h"
31 #include "util/u_memory.h"
32 #include "util/u_debug.h"
33 #include "util/u_simple_list.h"
34 
35 #include "rbug_public.h"
36 #include "rbug_screen.h"
37 #include "rbug_context.h"
38 #include "rbug_objects.h"
39 
40 DEBUG_GET_ONCE_BOOL_OPTION(rbug, "GALLIUM_RBUG", FALSE)
41 
42 static void
rbug_screen_destroy(struct pipe_screen * _screen)43 rbug_screen_destroy(struct pipe_screen *_screen)
44 {
45    struct rbug_screen *rb_screen = rbug_screen(_screen);
46    struct pipe_screen *screen = rb_screen->screen;
47 
48    screen->destroy(screen);
49 
50    FREE(rb_screen);
51 }
52 
53 static const char *
rbug_screen_get_name(struct pipe_screen * _screen)54 rbug_screen_get_name(struct pipe_screen *_screen)
55 {
56    struct rbug_screen *rb_screen = rbug_screen(_screen);
57    struct pipe_screen *screen = rb_screen->screen;
58 
59    return screen->get_name(screen);
60 }
61 
62 static const char *
rbug_screen_get_vendor(struct pipe_screen * _screen)63 rbug_screen_get_vendor(struct pipe_screen *_screen)
64 {
65    struct rbug_screen *rb_screen = rbug_screen(_screen);
66    struct pipe_screen *screen = rb_screen->screen;
67 
68    return screen->get_vendor(screen);
69 }
70 
71 static int
rbug_screen_get_param(struct pipe_screen * _screen,enum pipe_cap param)72 rbug_screen_get_param(struct pipe_screen *_screen,
73                       enum pipe_cap param)
74 {
75    struct rbug_screen *rb_screen = rbug_screen(_screen);
76    struct pipe_screen *screen = rb_screen->screen;
77 
78    return screen->get_param(screen,
79                             param);
80 }
81 
82 static int
rbug_screen_get_shader_param(struct pipe_screen * _screen,unsigned shader,enum pipe_shader_cap param)83 rbug_screen_get_shader_param(struct pipe_screen *_screen,
84                       unsigned shader, enum pipe_shader_cap param)
85 {
86    struct rbug_screen *rb_screen = rbug_screen(_screen);
87    struct pipe_screen *screen = rb_screen->screen;
88 
89    return screen->get_shader_param(screen, shader,
90                             param);
91 }
92 
93 static float
rbug_screen_get_paramf(struct pipe_screen * _screen,enum pipe_capf param)94 rbug_screen_get_paramf(struct pipe_screen *_screen,
95                        enum pipe_capf param)
96 {
97    struct rbug_screen *rb_screen = rbug_screen(_screen);
98    struct pipe_screen *screen = rb_screen->screen;
99 
100    return screen->get_paramf(screen,
101                              param);
102 }
103 
104 static boolean
rbug_screen_is_format_supported(struct pipe_screen * _screen,enum pipe_format format,enum pipe_texture_target target,unsigned sample_count,unsigned tex_usage)105 rbug_screen_is_format_supported(struct pipe_screen *_screen,
106                                 enum pipe_format format,
107                                 enum pipe_texture_target target,
108                                 unsigned sample_count,
109                                 unsigned tex_usage)
110 {
111    struct rbug_screen *rb_screen = rbug_screen(_screen);
112    struct pipe_screen *screen = rb_screen->screen;
113 
114    return screen->is_format_supported(screen,
115                                       format,
116                                       target,
117                                       sample_count,
118                                       tex_usage);
119 }
120 
121 static struct pipe_context *
rbug_screen_context_create(struct pipe_screen * _screen,void * priv)122 rbug_screen_context_create(struct pipe_screen *_screen,
123                            void *priv)
124 {
125    struct rbug_screen *rb_screen = rbug_screen(_screen);
126    struct pipe_screen *screen = rb_screen->screen;
127    struct pipe_context *result;
128 
129    result = screen->context_create(screen, priv);
130    if (result)
131       return rbug_context_create(_screen, result);
132    return NULL;
133 }
134 
135 static struct pipe_resource *
rbug_screen_resource_create(struct pipe_screen * _screen,const struct pipe_resource * templat)136 rbug_screen_resource_create(struct pipe_screen *_screen,
137                             const struct pipe_resource *templat)
138 {
139    struct rbug_screen *rb_screen = rbug_screen(_screen);
140    struct pipe_screen *screen = rb_screen->screen;
141    struct pipe_resource *result;
142 
143    result = screen->resource_create(screen,
144                                     templat);
145 
146    if (result)
147       return rbug_resource_create(rb_screen, result);
148    return NULL;
149 }
150 
151 static struct pipe_resource *
rbug_screen_resource_from_handle(struct pipe_screen * _screen,const struct pipe_resource * templ,struct winsys_handle * handle)152 rbug_screen_resource_from_handle(struct pipe_screen *_screen,
153                                  const struct pipe_resource *templ,
154                                  struct winsys_handle *handle)
155 {
156    struct rbug_screen *rb_screen = rbug_screen(_screen);
157    struct pipe_screen *screen = rb_screen->screen;
158    struct pipe_resource *result;
159 
160    result = screen->resource_from_handle(screen, templ, handle);
161 
162    result = rbug_resource_create(rbug_screen(_screen), result);
163 
164    return result;
165 }
166 
167 static boolean
rbug_screen_resource_get_handle(struct pipe_screen * _screen,struct pipe_resource * _resource,struct winsys_handle * handle)168 rbug_screen_resource_get_handle(struct pipe_screen *_screen,
169                                 struct pipe_resource *_resource,
170                                 struct winsys_handle *handle)
171 {
172    struct rbug_screen *rb_screen = rbug_screen(_screen);
173    struct rbug_resource *rb_resource = rbug_resource(_resource);
174    struct pipe_screen *screen = rb_screen->screen;
175    struct pipe_resource *resource = rb_resource->resource;
176 
177    return screen->resource_get_handle(screen, resource, handle);
178 }
179 
180 
181 
182 static void
rbug_screen_resource_destroy(struct pipe_screen * screen,struct pipe_resource * _resource)183 rbug_screen_resource_destroy(struct pipe_screen *screen,
184                              struct pipe_resource *_resource)
185 {
186    rbug_resource_destroy(rbug_resource(_resource));
187 }
188 
189 static void
rbug_screen_flush_frontbuffer(struct pipe_screen * _screen,struct pipe_resource * _resource,unsigned level,unsigned layer,void * context_private)190 rbug_screen_flush_frontbuffer(struct pipe_screen *_screen,
191                               struct pipe_resource *_resource,
192                               unsigned level, unsigned layer,
193                               void *context_private)
194 {
195    struct rbug_screen *rb_screen = rbug_screen(_screen);
196    struct rbug_resource *rb_resource = rbug_resource(_resource);
197    struct pipe_screen *screen = rb_screen->screen;
198    struct pipe_resource *resource = rb_resource->resource;
199 
200    screen->flush_frontbuffer(screen,
201                              resource,
202                              level, layer,
203                              context_private);
204 }
205 
206 static void
rbug_screen_fence_reference(struct pipe_screen * _screen,struct pipe_fence_handle ** ptr,struct pipe_fence_handle * fence)207 rbug_screen_fence_reference(struct pipe_screen *_screen,
208                             struct pipe_fence_handle **ptr,
209                             struct pipe_fence_handle *fence)
210 {
211    struct rbug_screen *rb_screen = rbug_screen(_screen);
212    struct pipe_screen *screen = rb_screen->screen;
213 
214    screen->fence_reference(screen,
215                            ptr,
216                            fence);
217 }
218 
219 static boolean
rbug_screen_fence_signalled(struct pipe_screen * _screen,struct pipe_fence_handle * fence)220 rbug_screen_fence_signalled(struct pipe_screen *_screen,
221                             struct pipe_fence_handle *fence)
222 {
223    struct rbug_screen *rb_screen = rbug_screen(_screen);
224    struct pipe_screen *screen = rb_screen->screen;
225 
226    return screen->fence_signalled(screen,
227                                   fence);
228 }
229 
230 static boolean
rbug_screen_fence_finish(struct pipe_screen * _screen,struct pipe_fence_handle * fence,uint64_t timeout)231 rbug_screen_fence_finish(struct pipe_screen *_screen,
232                          struct pipe_fence_handle *fence,
233                          uint64_t timeout)
234 {
235    struct rbug_screen *rb_screen = rbug_screen(_screen);
236    struct pipe_screen *screen = rb_screen->screen;
237 
238    return screen->fence_finish(screen,
239                                fence,
240                                timeout);
241 }
242 
243 boolean
rbug_enabled()244 rbug_enabled()
245 {
246    return debug_get_option_rbug();
247 }
248 
249 struct pipe_screen *
rbug_screen_create(struct pipe_screen * screen)250 rbug_screen_create(struct pipe_screen *screen)
251 {
252    struct rbug_screen *rb_screen;
253 
254    if (!debug_get_option_rbug())
255       return screen;
256 
257    rb_screen = CALLOC_STRUCT(rbug_screen);
258    if (!rb_screen)
259       return screen;
260 
261    pipe_mutex_init(rb_screen->list_mutex);
262    make_empty_list(&rb_screen->contexts);
263    make_empty_list(&rb_screen->resources);
264    make_empty_list(&rb_screen->surfaces);
265    make_empty_list(&rb_screen->transfers);
266 
267    rb_screen->base.destroy = rbug_screen_destroy;
268    rb_screen->base.get_name = rbug_screen_get_name;
269    rb_screen->base.get_vendor = rbug_screen_get_vendor;
270    rb_screen->base.get_param = rbug_screen_get_param;
271    rb_screen->base.get_shader_param = rbug_screen_get_shader_param;
272    rb_screen->base.get_paramf = rbug_screen_get_paramf;
273    rb_screen->base.is_format_supported = rbug_screen_is_format_supported;
274    rb_screen->base.context_create = rbug_screen_context_create;
275    rb_screen->base.resource_create = rbug_screen_resource_create;
276    rb_screen->base.resource_from_handle = rbug_screen_resource_from_handle;
277    rb_screen->base.resource_get_handle = rbug_screen_resource_get_handle;
278    rb_screen->base.resource_destroy = rbug_screen_resource_destroy;
279    rb_screen->base.flush_frontbuffer = rbug_screen_flush_frontbuffer;
280    rb_screen->base.fence_reference = rbug_screen_fence_reference;
281    rb_screen->base.fence_signalled = rbug_screen_fence_signalled;
282    rb_screen->base.fence_finish = rbug_screen_fence_finish;
283 
284    rb_screen->screen = screen;
285 
286    rb_screen->private_context = screen->context_create(screen, NULL);
287    if (!rb_screen->private_context)
288       goto err_free;
289 
290    rb_screen->rbug = rbug_start(rb_screen);
291 
292    if (!rb_screen->rbug)
293       goto err_context;
294 
295    return &rb_screen->base;
296 
297 err_context:
298    rb_screen->private_context->destroy(rb_screen->private_context);
299 err_free:
300    FREE(rb_screen);
301    return screen;
302 }
303