1/*
2 * Copyright 2010 Red Hat Inc.
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 <stdio.h>
24#include <errno.h>
25#include "pipe/p_defines.h"
26#include "pipe/p_state.h"
27#include "pipe/p_context.h"
28#include "pipe/p_screen.h"
29#include "util/u_memory.h"
30#include "util/u_inlines.h"
31#include "util/u_format.h"
32#include "noop_public.h"
33
34DEBUG_GET_ONCE_BOOL_OPTION(noop, "GALLIUM_NOOP", FALSE)
35
36void noop_init_state_functions(struct pipe_context *ctx);
37
38struct noop_pipe_screen {
39   struct pipe_screen	pscreen;
40   struct pipe_screen	*oscreen;
41};
42
43/*
44 * query
45 */
46struct noop_query {
47   unsigned	query;
48};
49static struct pipe_query *noop_create_query(struct pipe_context *ctx, unsigned query_type, unsigned index)
50{
51   struct noop_query *query = CALLOC_STRUCT(noop_query);
52
53   return (struct pipe_query *)query;
54}
55
56static void noop_destroy_query(struct pipe_context *ctx, struct pipe_query *query)
57{
58   FREE(query);
59}
60
61static boolean noop_begin_query(struct pipe_context *ctx, struct pipe_query *query)
62{
63   return true;
64}
65
66static bool noop_end_query(struct pipe_context *ctx, struct pipe_query *query)
67{
68   return true;
69}
70
71static boolean noop_get_query_result(struct pipe_context *ctx,
72                                     struct pipe_query *query,
73                                     boolean wait,
74                                     union pipe_query_result *vresult)
75{
76   uint64_t *result = (uint64_t*)vresult;
77
78   *result = 0;
79   return TRUE;
80}
81
82static void
83noop_set_active_query_state(struct pipe_context *pipe, boolean enable)
84{
85}
86
87
88/*
89 * resource
90 */
91struct noop_resource {
92   struct pipe_resource	base;
93   unsigned		size;
94   char			*data;
95   struct sw_displaytarget	*dt;
96};
97
98static struct pipe_resource *noop_resource_create(struct pipe_screen *screen,
99                                                  const struct pipe_resource *templ)
100{
101   struct noop_resource *nresource;
102   unsigned stride;
103
104   nresource = CALLOC_STRUCT(noop_resource);
105   if (!nresource)
106      return NULL;
107
108   stride = util_format_get_stride(templ->format, templ->width0);
109   nresource->base = *templ;
110   nresource->base.screen = screen;
111   nresource->size = stride * templ->height0 * templ->depth0;
112   nresource->data = MALLOC(nresource->size);
113   pipe_reference_init(&nresource->base.reference, 1);
114   if (nresource->data == NULL) {
115      FREE(nresource);
116      return NULL;
117   }
118   return &nresource->base;
119}
120
121static struct pipe_resource *noop_resource_from_handle(struct pipe_screen *screen,
122                                                       const struct pipe_resource *templ,
123                                                       struct winsys_handle *handle,
124                                                       unsigned usage)
125{
126   struct noop_pipe_screen *noop_screen = (struct noop_pipe_screen*)screen;
127   struct pipe_screen *oscreen = noop_screen->oscreen;
128   struct pipe_resource *result;
129   struct pipe_resource *noop_resource;
130
131   result = oscreen->resource_from_handle(oscreen, templ, handle, usage);
132   noop_resource = noop_resource_create(screen, result);
133   pipe_resource_reference(&result, NULL);
134   return noop_resource;
135}
136
137static boolean noop_resource_get_handle(struct pipe_screen *pscreen,
138                                        struct pipe_context *ctx,
139                                        struct pipe_resource *resource,
140                                        struct winsys_handle *handle,
141                                        unsigned usage)
142{
143   struct noop_pipe_screen *noop_screen = (struct noop_pipe_screen*)pscreen;
144   struct pipe_screen *screen = noop_screen->oscreen;
145   struct pipe_resource *tex;
146   bool result;
147
148   /* resource_get_handle musn't fail. Just create something and return it. */
149   tex = screen->resource_create(screen, resource);
150   if (!tex)
151      return false;
152
153   result = screen->resource_get_handle(screen, NULL, tex, handle, usage);
154   pipe_resource_reference(&tex, NULL);
155   return result;
156}
157
158static void noop_resource_destroy(struct pipe_screen *screen,
159                                  struct pipe_resource *resource)
160{
161   struct noop_resource *nresource = (struct noop_resource *)resource;
162
163   FREE(nresource->data);
164   FREE(resource);
165}
166
167
168/*
169 * transfer
170 */
171static void *noop_transfer_map(struct pipe_context *pipe,
172                               struct pipe_resource *resource,
173                               unsigned level,
174                               enum pipe_transfer_usage usage,
175                               const struct pipe_box *box,
176                               struct pipe_transfer **ptransfer)
177{
178   struct pipe_transfer *transfer;
179   struct noop_resource *nresource = (struct noop_resource *)resource;
180
181   transfer = CALLOC_STRUCT(pipe_transfer);
182   if (!transfer)
183      return NULL;
184   pipe_resource_reference(&transfer->resource, resource);
185   transfer->level = level;
186   transfer->usage = usage;
187   transfer->box = *box;
188   transfer->stride = 1;
189   transfer->layer_stride = 1;
190   *ptransfer = transfer;
191
192   return nresource->data;
193}
194
195static void noop_transfer_flush_region(struct pipe_context *pipe,
196                                       struct pipe_transfer *transfer,
197                                       const struct pipe_box *box)
198{
199}
200
201static void noop_transfer_unmap(struct pipe_context *pipe,
202                                struct pipe_transfer *transfer)
203{
204   pipe_resource_reference(&transfer->resource, NULL);
205   FREE(transfer);
206}
207
208static void noop_buffer_subdata(struct pipe_context *pipe,
209                                struct pipe_resource *resource,
210                                unsigned usage, unsigned offset,
211                                unsigned size, const void *data)
212{
213}
214
215static void noop_texture_subdata(struct pipe_context *pipe,
216                                 struct pipe_resource *resource,
217                                 unsigned level,
218                                 unsigned usage,
219                                 const struct pipe_box *box,
220                                 const void *data,
221                                 unsigned stride,
222                                 unsigned layer_stride)
223{
224}
225
226
227/*
228 * clear/copy
229 */
230static void noop_clear(struct pipe_context *ctx, unsigned buffers,
231                       const union pipe_color_union *color, double depth, unsigned stencil)
232{
233}
234
235static void noop_clear_render_target(struct pipe_context *ctx,
236                                     struct pipe_surface *dst,
237                                     const union pipe_color_union *color,
238                                     unsigned dstx, unsigned dsty,
239                                     unsigned width, unsigned height,
240                                     bool render_condition_enabled)
241{
242}
243
244static void noop_clear_depth_stencil(struct pipe_context *ctx,
245                                     struct pipe_surface *dst,
246                                     unsigned clear_flags,
247                                     double depth,
248                                     unsigned stencil,
249                                     unsigned dstx, unsigned dsty,
250                                     unsigned width, unsigned height,
251                                     bool render_condition_enabled)
252{
253}
254
255static void noop_resource_copy_region(struct pipe_context *ctx,
256                                      struct pipe_resource *dst,
257                                      unsigned dst_level,
258                                      unsigned dstx, unsigned dsty, unsigned dstz,
259                                      struct pipe_resource *src,
260                                      unsigned src_level,
261                                      const struct pipe_box *src_box)
262{
263}
264
265
266static void noop_blit(struct pipe_context *ctx,
267                      const struct pipe_blit_info *info)
268{
269}
270
271
272static void
273noop_flush_resource(struct pipe_context *ctx,
274                    struct pipe_resource *resource)
275{
276}
277
278
279/*
280 * context
281 */
282static void noop_flush(struct pipe_context *ctx,
283                       struct pipe_fence_handle **fence,
284                       unsigned flags)
285{
286   if (fence)
287      *fence = NULL;
288}
289
290static void noop_destroy_context(struct pipe_context *ctx)
291{
292   FREE(ctx);
293}
294
295static boolean noop_generate_mipmap(struct pipe_context *ctx,
296                                    struct pipe_resource *resource,
297                                    enum pipe_format format,
298                                    unsigned base_level,
299                                    unsigned last_level,
300                                    unsigned first_layer,
301                                    unsigned last_layer)
302{
303   return true;
304}
305
306static struct pipe_context *noop_create_context(struct pipe_screen *screen,
307                                                void *priv, unsigned flags)
308{
309   struct pipe_context *ctx = CALLOC_STRUCT(pipe_context);
310
311   if (!ctx)
312      return NULL;
313   ctx->screen = screen;
314   ctx->priv = priv;
315   ctx->destroy = noop_destroy_context;
316   ctx->flush = noop_flush;
317   ctx->clear = noop_clear;
318   ctx->clear_render_target = noop_clear_render_target;
319   ctx->clear_depth_stencil = noop_clear_depth_stencil;
320   ctx->resource_copy_region = noop_resource_copy_region;
321   ctx->generate_mipmap = noop_generate_mipmap;
322   ctx->blit = noop_blit;
323   ctx->flush_resource = noop_flush_resource;
324   ctx->create_query = noop_create_query;
325   ctx->destroy_query = noop_destroy_query;
326   ctx->begin_query = noop_begin_query;
327   ctx->end_query = noop_end_query;
328   ctx->get_query_result = noop_get_query_result;
329   ctx->set_active_query_state = noop_set_active_query_state;
330   ctx->transfer_map = noop_transfer_map;
331   ctx->transfer_flush_region = noop_transfer_flush_region;
332   ctx->transfer_unmap = noop_transfer_unmap;
333   ctx->buffer_subdata = noop_buffer_subdata;
334   ctx->texture_subdata = noop_texture_subdata;
335   noop_init_state_functions(ctx);
336
337   return ctx;
338}
339
340
341/*
342 * pipe_screen
343 */
344static void noop_flush_frontbuffer(struct pipe_screen *_screen,
345                                   struct pipe_resource *resource,
346                                   unsigned level, unsigned layer,
347                                   void *context_private, struct pipe_box *box)
348{
349}
350
351static const char *noop_get_vendor(struct pipe_screen* pscreen)
352{
353   return "X.Org";
354}
355
356static const char *noop_get_device_vendor(struct pipe_screen* pscreen)
357{
358   return "NONE";
359}
360
361static const char *noop_get_name(struct pipe_screen* pscreen)
362{
363   return "NOOP";
364}
365
366static int noop_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
367{
368   struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
369
370   return screen->get_param(screen, param);
371}
372
373static float noop_get_paramf(struct pipe_screen* pscreen,
374                             enum pipe_capf param)
375{
376   struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
377
378   return screen->get_paramf(screen, param);
379}
380
381static int noop_get_shader_param(struct pipe_screen* pscreen, unsigned shader, enum pipe_shader_cap param)
382{
383   struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
384
385   return screen->get_shader_param(screen, shader, param);
386}
387
388static int noop_get_compute_param(struct pipe_screen *pscreen,
389                                  enum pipe_shader_ir ir_type,
390                                  enum pipe_compute_cap param,
391                                  void *ret)
392{
393   struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
394
395   return screen->get_compute_param(screen, ir_type, param, ret);
396}
397
398static boolean noop_is_format_supported(struct pipe_screen* pscreen,
399                                        enum pipe_format format,
400                                        enum pipe_texture_target target,
401                                        unsigned sample_count,
402                                        unsigned usage)
403{
404   struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
405
406   return screen->is_format_supported(screen, format, target, sample_count, usage);
407}
408
409static uint64_t noop_get_timestamp(struct pipe_screen *pscreen)
410{
411   return 0;
412}
413
414static void noop_destroy_screen(struct pipe_screen *screen)
415{
416   struct noop_pipe_screen *noop_screen = (struct noop_pipe_screen*)screen;
417   struct pipe_screen *oscreen = noop_screen->oscreen;
418
419   oscreen->destroy(oscreen);
420   FREE(screen);
421}
422
423static void noop_fence_reference(struct pipe_screen *screen,
424                          struct pipe_fence_handle **ptr,
425                          struct pipe_fence_handle *fence)
426{
427}
428
429static boolean noop_fence_finish(struct pipe_screen *screen,
430                                 struct pipe_context *ctx,
431                                 struct pipe_fence_handle *fence,
432                                 uint64_t timeout)
433{
434   return true;
435}
436
437static void noop_query_memory_info(struct pipe_screen *pscreen,
438                                   struct pipe_memory_info *info)
439{
440   struct noop_pipe_screen *noop_screen = (struct noop_pipe_screen*)pscreen;
441   struct pipe_screen *screen = noop_screen->oscreen;
442
443   screen->query_memory_info(screen, info);
444}
445
446struct pipe_screen *noop_screen_create(struct pipe_screen *oscreen)
447{
448   struct noop_pipe_screen *noop_screen;
449   struct pipe_screen *screen;
450
451   if (!debug_get_option_noop()) {
452      return oscreen;
453   }
454
455   noop_screen = CALLOC_STRUCT(noop_pipe_screen);
456   if (!noop_screen) {
457      return NULL;
458   }
459   noop_screen->oscreen = oscreen;
460   screen = &noop_screen->pscreen;
461
462   screen->destroy = noop_destroy_screen;
463   screen->get_name = noop_get_name;
464   screen->get_vendor = noop_get_vendor;
465   screen->get_device_vendor = noop_get_device_vendor;
466   screen->get_param = noop_get_param;
467   screen->get_shader_param = noop_get_shader_param;
468   screen->get_compute_param = noop_get_compute_param;
469   screen->get_paramf = noop_get_paramf;
470   screen->is_format_supported = noop_is_format_supported;
471   screen->context_create = noop_create_context;
472   screen->resource_create = noop_resource_create;
473   screen->resource_from_handle = noop_resource_from_handle;
474   screen->resource_get_handle = noop_resource_get_handle;
475   screen->resource_destroy = noop_resource_destroy;
476   screen->flush_frontbuffer = noop_flush_frontbuffer;
477   screen->get_timestamp = noop_get_timestamp;
478   screen->fence_reference = noop_fence_reference;
479   screen->fence_finish = noop_fence_finish;
480   screen->query_memory_info = noop_query_memory_info;
481
482   return screen;
483}
484