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
40DEBUG_GET_ONCE_BOOL_OPTION(rbug, "GALLIUM_RBUG", FALSE)
41
42static void
43rbug_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
53static const char *
54rbug_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
62static const char *
63rbug_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
71static int
72rbug_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
82static int
83rbug_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
93static float
94rbug_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
104static boolean
105rbug_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
121static struct pipe_context *
122rbug_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
135static struct pipe_resource *
136rbug_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
151static struct pipe_resource *
152rbug_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
167static boolean
168rbug_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
182static void
183rbug_screen_resource_destroy(struct pipe_screen *screen,
184                             struct pipe_resource *_resource)
185{
186   rbug_resource_destroy(rbug_resource(_resource));
187}
188
189static void
190rbug_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
206static void
207rbug_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
219static boolean
220rbug_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
230static boolean
231rbug_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
243boolean
244rbug_enabled()
245{
246   return debug_get_option_rbug();
247}
248
249struct pipe_screen *
250rbug_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
297err_context:
298   rb_screen->private_context->destroy(rb_screen->private_context);
299err_free:
300   FREE(rb_screen);
301   return screen;
302}
303