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