xlib: allow winsys's to register themselves with glx/xlib state tracker
[mesa.git] / src / gallium / winsys / xlib / xlib_brw_screen.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 *
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Keith Whitwell
32 * Brian Paul
33 */
34
35
36 //#include "state_trackers/xlib/glxheader.h"
37 //#include "state_trackers/xlib/xmesaP.h"
38
39 #include "pipe/p_winsys.h"
40 #include "pipe/p_inlines.h"
41 #include "util/u_math.h"
42 #include "util/u_memory.h"
43 #include "i965simple/brw_winsys.h"
44 #include "i965simple/brw_screen.h"
45
46 #include "xlib_brw_aub.h"
47 #include "xlib_brw.h"
48 #include "xlib.h"
49
50
51
52 struct aub_buffer {
53 char *data;
54 unsigned offset;
55 unsigned size;
56 unsigned refcount;
57 unsigned map_count;
58 boolean dump_on_unmap;
59 };
60
61
62
63 struct aub_pipe_winsys {
64 struct pipe_winsys winsys;
65
66 struct brw_aubfile *aubfile;
67
68 /* This is simple, isn't it:
69 */
70 char *pool;
71 unsigned size;
72 unsigned used;
73 };
74
75
76 /* Turn a pipe winsys into an aub/pipe winsys:
77 */
78 static inline struct aub_pipe_winsys *
79 aub_pipe_winsys( struct pipe_winsys *winsys )
80 {
81 return (struct aub_pipe_winsys *)winsys;
82 }
83
84
85
86 static INLINE struct aub_buffer *
87 aub_bo( struct pipe_buffer *bo )
88 {
89 return (struct aub_buffer *)bo;
90 }
91
92 static INLINE struct pipe_buffer *
93 pipe_bo( struct aub_buffer *bo )
94 {
95 return (struct pipe_buffer *)bo;
96 }
97
98
99
100
101 static void *aub_buffer_map(struct pipe_winsys *winsys,
102 struct pipe_buffer *buf,
103 unsigned flags )
104 {
105 struct aub_buffer *sbo = aub_bo(buf);
106
107 assert(sbo->data);
108
109 if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
110 sbo->dump_on_unmap = 1;
111
112 sbo->map_count++;
113 return sbo->data;
114 }
115
116 static void aub_buffer_unmap(struct pipe_winsys *winsys,
117 struct pipe_buffer *buf)
118 {
119 struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
120 struct aub_buffer *sbo = aub_bo(buf);
121
122 sbo->map_count--;
123
124 if (sbo->map_count == 0 &&
125 sbo->dump_on_unmap) {
126
127 sbo->dump_on_unmap = 0;
128
129 brw_aub_gtt_data( iws->aubfile,
130 sbo->offset,
131 sbo->data,
132 sbo->size,
133 0,
134 0);
135 }
136 }
137
138
139 static void
140 aub_buffer_destroy(struct pipe_winsys *winsys,
141 struct pipe_buffer *buf)
142 {
143 free(buf);
144 }
145
146
147
148 void xlib_brw_commands_aub(struct pipe_winsys *winsys,
149 unsigned *cmds,
150 unsigned nr_dwords)
151 {
152 struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
153 unsigned size = nr_dwords * 4;
154
155 assert(iws->used + size < iws->size);
156
157 brw_aub_gtt_cmds( iws->aubfile,
158 AUB_BUF_START + iws->used,
159 cmds,
160 nr_dwords * sizeof(int) );
161
162 iws->used += align(size, 4096);
163 }
164
165
166 /* XXX: fix me:
167 */
168 static struct aub_pipe_winsys *global_winsys = NULL;
169
170
171
172
173 /* Pipe has no concept of pools. We choose the tex/region pool
174 * for all buffers.
175 */
176 static struct pipe_buffer *
177 aub_buffer_create(struct pipe_winsys *winsys,
178 unsigned alignment,
179 unsigned usage,
180 unsigned size)
181 {
182 struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
183 struct aub_buffer *sbo = CALLOC_STRUCT(aub_buffer);
184
185 sbo->refcount = 1;
186
187 /* Could reuse buffers that are not referenced in current
188 * batchbuffer. Can't do that atm, so always reallocate:
189 */
190 assert(iws->used + size < iws->size);
191 sbo->data = iws->pool + iws->used;
192 sbo->offset = AUB_BUF_START + iws->used;
193 iws->used += align(size, 4096);
194
195 sbo->size = size;
196
197 return pipe_bo(sbo);
198 }
199
200
201 static struct pipe_buffer *
202 aub_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes)
203 {
204 struct aub_buffer *sbo;
205
206 /* Lets hope this is meant for upload, not as a result!
207 */
208 sbo = aub_bo(aub_buffer_create( winsys, 0, 0, 0 ));
209
210 sbo->data = ptr;
211 sbo->size = bytes;
212
213 return pipe_bo(sbo);
214 }
215
216
217 /* The state tracker (should!) keep track of whether the fake
218 * frontbuffer has been touched by any rendering since the last time
219 * we copied its contents to the real frontbuffer. Our task is easy:
220 */
221 static void
222 aub_flush_frontbuffer( struct pipe_winsys *winsys,
223 struct pipe_surface *surface,
224 void *context_private)
225 {
226 // struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
227 brw_aub_dump_bmp( global_winsys->aubfile,
228 surface,
229 aub_bo(surface->buffer)->offset );
230 }
231
232 static struct pipe_surface *
233 aub_i915_surface_alloc(struct pipe_winsys *winsys)
234 {
235 struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface);
236 if (surf) {
237 surf->refcount = 1;
238 surf->winsys = winsys;
239 }
240 return surf;
241 }
242
243
244 /**
245 * Round n up to next multiple.
246 */
247 static INLINE unsigned
248 round_up(unsigned n, unsigned multiple)
249 {
250 return (n + multiple - 1) & ~(multiple - 1);
251 }
252
253 static int
254 aub_i915_surface_alloc_storage(struct pipe_winsys *winsys,
255 struct pipe_surface *surf,
256 unsigned width, unsigned height,
257 enum pipe_format format,
258 unsigned flags,
259 unsigned tex_usage)
260 {
261 const unsigned alignment = 64;
262
263 surf->width = width;
264 surf->height = height;
265 surf->format = format;
266 pf_get_block(format, &surf->block);
267 surf->nblocksx = pf_get_nblocksx(&surf->block, width);
268 surf->nblocksy = pf_get_nblocksy(&surf->block, height);
269 surf->stride = round_up(surf->nblocksx * surf->block.size, alignment);
270 surf->usage = flags;
271
272 assert(!surf->buffer);
273 surf->buffer = winsys->buffer_create(winsys, alignment,
274 PIPE_BUFFER_USAGE_PIXEL,
275 surf->stride * surf->nblocksy);
276 if(!surf->buffer)
277 return -1;
278
279 return 0;
280 }
281
282 static void
283 aub_i915_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
284 {
285 struct pipe_surface *surf = *s;
286 surf->refcount--;
287 if (surf->refcount == 0) {
288 if (surf->buffer)
289 winsys_buffer_reference(winsys, &surf->buffer, NULL);
290 free(surf);
291 }
292 *s = NULL;
293 }
294
295
296
297 static const char *
298 aub_get_name( struct pipe_winsys *winsys )
299 {
300 return "Aub/xlib";
301 }
302
303 static void
304 xlib_brw_destroy_pipe_winsys_aub( struct pipe_winsys *winsys )
305
306 {
307 struct aub_pipe_winsys *iws = aub_pipe_winsys(winsys);
308 brw_aub_destroy(iws->aubfile);
309 free(iws->pool);
310 free(iws);
311 }
312
313
314
315 static struct pipe_winsys *
316 xlib_create_brw_winsys( void )
317 {
318 struct aub_pipe_winsys *iws = CALLOC_STRUCT( aub_pipe_winsys );
319
320 /* Fill in this struct with callbacks that pipe will need to
321 * communicate with the window system, buffer manager, etc.
322 *
323 * Pipe would be happy with a malloc based memory manager, but
324 * the SwapBuffers implementation in this winsys driver requires
325 * that rendering be done to an appropriate _DriBufferObject.
326 */
327 iws->winsys.buffer_create = aub_buffer_create;
328 iws->winsys.user_buffer_create = aub_user_buffer_create;
329 iws->winsys.buffer_map = aub_buffer_map;
330 iws->winsys.buffer_unmap = aub_buffer_unmap;
331 iws->winsys.buffer_destroy = aub_buffer_destroy;
332 iws->winsys.flush_frontbuffer = aub_flush_frontbuffer;
333 iws->winsys.get_name = aub_get_name;
334 iws->winsys.destroy = xlib_brw_destroy_pipe_winsys_aub;
335
336 iws->winsys.surface_alloc = aub_i915_surface_alloc;
337 iws->winsys.surface_alloc_storage = aub_i915_surface_alloc_storage;
338 iws->winsys.surface_release = aub_i915_surface_release;
339
340 iws->aubfile = brw_aubfile_create();
341 iws->size = AUB_BUF_SIZE;
342 iws->pool = malloc(AUB_BUF_SIZE);
343
344 /* HACK: static copy of this pointer:
345 */
346 assert(global_winsys == NULL);
347 global_winsys = iws;
348
349 return &iws->winsys;
350 }
351
352
353 static struct pipe_screen *
354 xlib_create_brw_screen( struct pipe_winsys *winsys )
355 {
356 return brw_create_screen(winsys, 0/* XXX pci_id */);
357 }
358
359
360 /* These per-screen functions are acually made available to the driver
361 * through the brw_winsys (per-context) entity.
362 */
363 unsigned xlib_brw_get_buffer_offset( struct pipe_winsys *pws,
364 struct pipe_buffer *buf,
365 unsigned access_flags )
366 {
367 return aub_bo(buf)->offset;
368 }
369
370 void xlib_brw_buffer_subdata_typed( struct pipe_winsys *pws,
371 struct pipe_buffer *buf,
372 unsigned long offset,
373 unsigned long size,
374 const void *data,
375 unsigned data_type )
376 {
377 unsigned aub_type = DW_GENERAL_STATE;
378 unsigned aub_sub_type;
379
380 switch (data_type) {
381 case BRW_CC_VP:
382 aub_sub_type = DWGS_COLOR_CALC_VIEWPORT_STATE;
383 break;
384 case BRW_CC_UNIT:
385 aub_sub_type = DWGS_COLOR_CALC_STATE;
386 break;
387 case BRW_WM_PROG:
388 aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
389 break;
390 case BRW_SAMPLER_DEFAULT_COLOR:
391 aub_sub_type = DWGS_SAMPLER_DEFAULT_COLOR;
392 break;
393 case BRW_SAMPLER:
394 aub_sub_type = DWGS_SAMPLER_STATE;
395 break;
396 case BRW_WM_UNIT:
397 aub_sub_type = DWGS_WINDOWER_IZ_STATE;
398 break;
399 case BRW_SF_PROG:
400 aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
401 break;
402 case BRW_SF_VP:
403 aub_sub_type = DWGS_STRIPS_FANS_VIEWPORT_STATE;
404 break;
405 case BRW_SF_UNIT:
406 aub_sub_type = DWGS_STRIPS_FANS_STATE;
407 break;
408 case BRW_VS_UNIT:
409 aub_sub_type = DWGS_VERTEX_SHADER_STATE;
410 break;
411 case BRW_VS_PROG:
412 aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
413 break;
414 case BRW_GS_UNIT:
415 aub_sub_type = DWGS_GEOMETRY_SHADER_STATE;
416 break;
417 case BRW_GS_PROG:
418 aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
419 break;
420 case BRW_CLIP_VP:
421 aub_sub_type = DWGS_CLIPPER_VIEWPORT_STATE;
422 break;
423 case BRW_CLIP_UNIT:
424 aub_sub_type = DWGS_CLIPPER_STATE;
425 break;
426 case BRW_CLIP_PROG:
427 aub_sub_type = DWGS_KERNEL_INSTRUCTIONS;
428 break;
429 case BRW_SS_SURFACE:
430 aub_type = DW_SURFACE_STATE;
431 aub_sub_type = DWSS_SURFACE_STATE;
432 break;
433 case BRW_SS_SURF_BIND:
434 aub_type = DW_SURFACE_STATE;
435 aub_sub_type = DWSS_BINDING_TABLE_STATE;
436 break;
437 case BRW_CONSTANT_BUFFER:
438 aub_type = DW_CONSTANT_URB_ENTRY;
439 aub_sub_type = 0;
440 break;
441
442 default:
443 assert(0);
444 break;
445 }
446
447 {
448 struct aub_pipe_winsys *iws = aub_pipe_winsys(pws);
449 struct aub_buffer *sbo = aub_bo(buf);
450
451 assert(sbo->size > offset + size);
452 memcpy(sbo->data + offset, data, size);
453
454 brw_aub_gtt_data( iws->aubfile,
455 sbo->offset + offset,
456 sbo->data + offset,
457 size,
458 aub_type,
459 aub_sub_type );
460 }
461 }
462
463
464 static void
465 xlib_brw_display_surface(struct xmesa_buffer *b,
466 struct pipe_surface *surf)
467 {
468 brw_aub_dump_bmp( global_winsys->aubfile,
469 surf,
470 aub_bo(surf->buffer)->offset );
471 }
472
473
474 struct xm_driver xlib_brw_driver =
475 {
476 .create_pipe_winsys = xlib_create_brw_winsys,
477 .create_pipe_screen = xlib_create_brw_screen,
478 .create_pipe_context = xlib_create_brw_context,
479 .display_surface = xlib_brw_display_surface,
480 };