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)
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 void noop_begin_query(struct pipe_context *ctx, struct pipe_query *query)
62{
63}
64
65static void noop_end_query(struct pipe_context *ctx, struct pipe_query *query)
66{
67}
68
69static boolean noop_get_query_result(struct pipe_context *ctx,
70					struct pipe_query *query,
71					boolean wait,
72					union pipe_query_result *vresult)
73{
74	uint64_t *result = (uint64_t*)vresult;
75
76	*result = 0;
77	return TRUE;
78}
79
80
81/*
82 * resource
83 */
84struct noop_resource {
85	struct pipe_resource	base;
86	unsigned		size;
87	char			*data;
88	struct sw_displaytarget	*dt;
89};
90
91static struct pipe_resource *noop_resource_create(struct pipe_screen *screen,
92						const struct pipe_resource *templ)
93{
94	struct noop_resource *nresource;
95	unsigned stride;
96
97	nresource = CALLOC_STRUCT(noop_resource);
98	if (nresource == NULL)
99		return NULL;
100
101	stride = util_format_get_stride(templ->format, templ->width0);
102	nresource->base = *templ;
103	nresource->base.screen = screen;
104	nresource->size = stride * templ->height0 * templ->depth0;
105	nresource->data = MALLOC(nresource->size);
106	pipe_reference_init(&nresource->base.reference, 1);
107	if (nresource->data == NULL) {
108		FREE(nresource);
109		return NULL;
110	}
111	return &nresource->base;
112}
113
114static struct pipe_resource *noop_resource_from_handle(struct pipe_screen *screen,
115							const struct pipe_resource *templ,
116							struct winsys_handle *handle)
117{
118	struct noop_pipe_screen *noop_screen = (struct noop_pipe_screen*)screen;
119	struct pipe_screen *oscreen = noop_screen->oscreen;
120	struct pipe_resource *result;
121	struct pipe_resource *noop_resource;
122
123	result = oscreen->resource_from_handle(oscreen, templ, handle);
124	noop_resource = noop_resource_create(screen, result);
125	pipe_resource_reference(&result, NULL);
126	return noop_resource;
127}
128
129static boolean noop_resource_get_handle(struct pipe_screen *screen,
130					struct pipe_resource *resource,
131					struct winsys_handle *handle)
132{
133	return FALSE;
134}
135
136static void noop_resource_destroy(struct pipe_screen *screen,
137					struct pipe_resource *resource)
138{
139	struct noop_resource *nresource = (struct noop_resource *)resource;
140
141	FREE(nresource->data);
142	FREE(resource);
143}
144
145
146/*
147 * transfer
148 */
149static struct pipe_transfer *noop_get_transfer(struct pipe_context *context,
150						struct pipe_resource *resource,
151						unsigned level,
152						enum pipe_transfer_usage usage,
153						const struct pipe_box *box)
154{
155	struct pipe_transfer *transfer;
156
157	transfer = CALLOC_STRUCT(pipe_transfer);
158	if (transfer == NULL)
159		return NULL;
160	pipe_resource_reference(&transfer->resource, resource);
161	transfer->level = level;
162	transfer->usage = usage;
163	transfer->box = *box;
164	transfer->stride = 1;
165	transfer->layer_stride = 1;
166	return transfer;
167}
168
169static void *noop_transfer_map(struct pipe_context *pipe,
170				struct pipe_transfer *transfer)
171{
172	struct noop_resource *nresource = (struct noop_resource *)transfer->resource;
173
174	return nresource->data;
175}
176
177static void noop_transfer_flush_region(struct pipe_context *pipe,
178					struct pipe_transfer *transfer,
179					const struct pipe_box *box)
180{
181}
182
183static void noop_transfer_unmap(struct pipe_context *pipe,
184				struct pipe_transfer *transfer)
185{
186}
187
188static void noop_transfer_destroy(struct pipe_context *pipe,
189					struct pipe_transfer *transfer)
190{
191	pipe_resource_reference(&transfer->resource, NULL);
192	FREE(transfer);
193}
194
195static void noop_transfer_inline_write(struct pipe_context *pipe,
196					struct pipe_resource *resource,
197					unsigned level,
198					unsigned usage,
199					const struct pipe_box *box,
200					const void *data,
201					unsigned stride,
202					unsigned layer_stride)
203{
204}
205
206
207/*
208 * clear/copy
209 */
210static void noop_clear(struct pipe_context *ctx, unsigned buffers,
211		       const union pipe_color_union *color, double depth, unsigned stencil)
212{
213}
214
215static void noop_clear_render_target(struct pipe_context *ctx,
216				     struct pipe_surface *dst,
217				     const union pipe_color_union *color,
218				     unsigned dstx, unsigned dsty,
219				     unsigned width, unsigned height)
220{
221}
222
223static void noop_clear_depth_stencil(struct pipe_context *ctx,
224				     struct pipe_surface *dst,
225				     unsigned clear_flags,
226				     double depth,
227				     unsigned stencil,
228				     unsigned dstx, unsigned dsty,
229				     unsigned width, unsigned height)
230{
231}
232
233static void noop_resource_copy_region(struct pipe_context *ctx,
234				      struct pipe_resource *dst,
235				      unsigned dst_level,
236				      unsigned dstx, unsigned dsty, unsigned dstz,
237				      struct pipe_resource *src,
238				      unsigned src_level,
239				      const struct pipe_box *src_box)
240{
241}
242
243
244/*
245 * context
246 */
247static void noop_flush(struct pipe_context *ctx,
248			struct pipe_fence_handle **fence)
249{
250}
251
252static void noop_destroy_context(struct pipe_context *ctx)
253{
254	FREE(ctx);
255}
256
257static struct pipe_context *noop_create_context(struct pipe_screen *screen, void *priv)
258{
259	struct pipe_context *ctx = CALLOC_STRUCT(pipe_context);
260
261	if (ctx == NULL)
262		return NULL;
263	ctx->screen = screen;
264	ctx->priv = priv;
265	ctx->destroy = noop_destroy_context;
266	ctx->flush = noop_flush;
267	ctx->clear = noop_clear;
268	ctx->clear_render_target = noop_clear_render_target;
269	ctx->clear_depth_stencil = noop_clear_depth_stencil;
270	ctx->resource_copy_region = noop_resource_copy_region;
271	ctx->create_query = noop_create_query;
272	ctx->destroy_query = noop_destroy_query;
273	ctx->begin_query = noop_begin_query;
274	ctx->end_query = noop_end_query;
275	ctx->get_query_result = noop_get_query_result;
276	ctx->get_transfer = noop_get_transfer;
277	ctx->transfer_map = noop_transfer_map;
278	ctx->transfer_flush_region = noop_transfer_flush_region;
279	ctx->transfer_unmap = noop_transfer_unmap;
280	ctx->transfer_destroy = noop_transfer_destroy;
281	ctx->transfer_inline_write = noop_transfer_inline_write;
282	noop_init_state_functions(ctx);
283
284	return ctx;
285}
286
287
288/*
289 * pipe_screen
290 */
291static void noop_flush_frontbuffer(struct pipe_screen *_screen,
292				   struct pipe_resource *resource,
293				   unsigned level, unsigned layer,
294				   void *context_private)
295{
296}
297
298static const char *noop_get_vendor(struct pipe_screen* pscreen)
299{
300	return "X.Org";
301}
302
303static const char *noop_get_name(struct pipe_screen* pscreen)
304{
305	return "NOOP";
306}
307
308static int noop_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
309{
310	struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
311
312	return screen->get_param(screen, param);
313}
314
315static float noop_get_paramf(struct pipe_screen* pscreen,
316			     enum pipe_capf param)
317{
318	struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
319
320	return screen->get_paramf(screen, param);
321}
322
323static int noop_get_shader_param(struct pipe_screen* pscreen, unsigned shader, enum pipe_shader_cap param)
324{
325	struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
326
327	return screen->get_shader_param(screen, shader, param);
328}
329
330static boolean noop_is_format_supported(struct pipe_screen* pscreen,
331					enum pipe_format format,
332					enum pipe_texture_target target,
333					unsigned sample_count,
334                                        unsigned usage)
335{
336	struct pipe_screen *screen = ((struct noop_pipe_screen*)pscreen)->oscreen;
337
338	return screen->is_format_supported(screen, format, target, sample_count, usage);
339}
340
341static uint64_t noop_get_timestamp(struct pipe_screen *pscreen)
342{
343	return 0;
344}
345
346static void noop_destroy_screen(struct pipe_screen *screen)
347{
348	struct noop_pipe_screen *noop_screen = (struct noop_pipe_screen*)screen;
349	struct pipe_screen *oscreen = noop_screen->oscreen;
350
351	oscreen->destroy(oscreen);
352	FREE(screen);
353}
354
355struct pipe_screen *noop_screen_create(struct pipe_screen *oscreen)
356{
357	struct noop_pipe_screen *noop_screen;
358	struct pipe_screen *screen;
359
360	if (!debug_get_option_noop()) {
361		return oscreen;
362	}
363
364	noop_screen = CALLOC_STRUCT(noop_pipe_screen);
365	if (noop_screen == NULL) {
366		return NULL;
367	}
368	noop_screen->oscreen = oscreen;
369	screen = &noop_screen->pscreen;
370
371	screen->destroy = noop_destroy_screen;
372	screen->get_name = noop_get_name;
373	screen->get_vendor = noop_get_vendor;
374	screen->get_param = noop_get_param;
375	screen->get_shader_param = noop_get_shader_param;
376	screen->get_paramf = noop_get_paramf;
377	screen->is_format_supported = noop_is_format_supported;
378	screen->context_create = noop_create_context;
379	screen->resource_create = noop_resource_create;
380	screen->resource_from_handle = noop_resource_from_handle;
381	screen->resource_get_handle = noop_resource_get_handle;
382	screen->resource_destroy = noop_resource_destroy;
383	screen->flush_frontbuffer = noop_flush_frontbuffer;
384        screen->get_timestamp = noop_get_timestamp;
385
386	return screen;
387}
388