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