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