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