Merge commit 'origin/7.8'
[mesa.git] / src / gallium / winsys / i965 / xlib / xlib_i965.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 "util/u_memory.h"
37 #include "util/u_math.h"
38 #include "pipe/p_error.h"
39 #include "pipe/p_context.h"
40
41 #include "xm_public.h"
42
43 #include "i965/brw_winsys.h"
44 #include "i965/brw_screen.h"
45 #include "i965/brw_reg.h"
46 #include "i965/brw_structs_dump.h"
47
48 #define MAX_VRAM (128*1024*1024)
49
50
51
52 extern int brw_disasm (FILE *file,
53 const struct brw_instruction *inst,
54 unsigned count );
55
56 extern int intel_decode(const uint32_t *data,
57 int count,
58 uint32_t hw_offset,
59 uint32_t devid);
60
61 struct xlib_brw_buffer
62 {
63 struct brw_winsys_buffer base;
64 char *virtual;
65 unsigned offset;
66 unsigned type;
67 int map_count;
68 boolean modified;
69 };
70
71
72 /**
73 * Subclass of brw_winsys_screen for Xlib winsys
74 */
75 struct xlib_brw_winsys
76 {
77 struct brw_winsys_screen base;
78 struct brw_chipset chipset;
79
80 unsigned size;
81 unsigned used;
82 };
83
84 static struct xlib_brw_winsys *
85 xlib_brw_winsys( struct brw_winsys_screen *screen )
86 {
87 return (struct xlib_brw_winsys *)screen;
88 }
89
90
91 static struct xlib_brw_buffer *
92 xlib_brw_buffer( struct brw_winsys_buffer *buffer )
93 {
94 return (struct xlib_brw_buffer *)buffer;
95 }
96
97
98
99 const char *names[BRW_BUFFER_TYPE_MAX] = {
100 "TEXTURE",
101 "SCANOUT",
102 "VERTEX",
103 "CURBE",
104 "QUERY",
105 "SHADER_CONSTANTS",
106 "WM_SCRATCH",
107 "BATCH",
108 "GENERAL_STATE",
109 "SURFACE_STATE",
110 "PIXEL",
111 "GENERIC",
112 };
113
114 const char *usages[BRW_USAGE_MAX] = {
115 "STATE",
116 "QUERY_RESULT",
117 "RENDER_TARGET",
118 "DEPTH_BUFFER",
119 "BLIT_SOURCE",
120 "BLIT_DEST",
121 "SAMPLER",
122 "VERTEX",
123 "SCRATCH"
124 };
125
126
127 const char *data_types[BRW_DATA_MAX] =
128 {
129 "GS: CC_VP",
130 "GS: CC_UNIT",
131 "GS: WM_PROG",
132 "GS: SAMPLER_DEFAULT_COLOR",
133 "GS: SAMPLER",
134 "GS: WM_UNIT",
135 "GS: SF_PROG",
136 "GS: SF_VP",
137 "GS: SF_UNIT",
138 "GS: VS_UNIT",
139 "GS: VS_PROG",
140 "GS: GS_UNIT",
141 "GS: GS_PROG",
142 "GS: CLIP_VP",
143 "GS: CLIP_UNIT",
144 "GS: CLIP_PROG",
145 "SS: SURFACE",
146 "SS: SURF_BIND",
147 "CONSTANT DATA",
148 "BATCH DATA",
149 "(untyped)"
150 };
151
152
153 static enum pipe_error
154 xlib_brw_bo_alloc( struct brw_winsys_screen *sws,
155 enum brw_buffer_type type,
156 unsigned size,
157 unsigned alignment,
158 struct brw_winsys_buffer **bo_out )
159 {
160 struct xlib_brw_winsys *xbw = xlib_brw_winsys(sws);
161 struct xlib_brw_buffer *buf;
162
163 if (BRW_DEBUG & DEBUG_WINSYS)
164 debug_printf("%s type %s sz %d align %d\n",
165 __FUNCTION__, names[type], size, alignment );
166
167 buf = CALLOC_STRUCT(xlib_brw_buffer);
168 if (!buf)
169 return PIPE_ERROR_OUT_OF_MEMORY;
170
171 pipe_reference_init(&buf->base.reference, 1);
172
173 buf->offset = align(xbw->used, alignment);
174 buf->type = type;
175 buf->virtual = MALLOC(size);
176 buf->base.size = size;
177 buf->base.sws = sws;
178
179 xbw->used = align(xbw->used, alignment) + size;
180 if (xbw->used > MAX_VRAM)
181 goto err;
182
183 /* XXX: possibly rentrant call to bo_destroy:
184 */
185 bo_reference(bo_out, &buf->base);
186 return PIPE_OK;
187
188 err:
189 assert(0);
190 FREE(buf->virtual);
191 FREE(buf);
192 return PIPE_ERROR_OUT_OF_MEMORY;
193 }
194
195 static void
196 xlib_brw_bo_destroy( struct brw_winsys_buffer *buffer )
197 {
198 struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer);
199
200 FREE(buf);
201 }
202
203 static int
204 xlib_brw_bo_emit_reloc( struct brw_winsys_buffer *buffer,
205 enum brw_buffer_usage usage,
206 unsigned delta,
207 unsigned offset,
208 struct brw_winsys_buffer *buffer2)
209 {
210 struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer);
211 struct xlib_brw_buffer *buf2 = xlib_brw_buffer(buffer2);
212
213 if (BRW_DEBUG & DEBUG_WINSYS)
214 debug_printf("%s buf %p offset %x val %x + %x buf2 %p/%s/%s\n",
215 __FUNCTION__, (void *)buffer, offset,
216 buf2->offset, delta,
217 (void *)buffer2, names[buf2->type], usages[usage]);
218
219 *(uint32_t *)(buf->virtual + offset) = buf2->offset + delta;
220
221 return 0;
222 }
223
224 static int
225 xlib_brw_bo_exec( struct brw_winsys_buffer *buffer,
226 unsigned bytes_used )
227 {
228 if (BRW_DEBUG & DEBUG_WINSYS)
229 debug_printf("execute buffer %p, bytes %d\n", (void *)buffer, bytes_used);
230
231 return 0;
232 }
233
234
235
236
237 static int
238 xlib_brw_bo_subdata(struct brw_winsys_buffer *buffer,
239 enum brw_buffer_data_type data_type,
240 size_t offset,
241 size_t size,
242 const void *data,
243 const struct brw_winsys_reloc *reloc,
244 unsigned nr_relocs)
245 {
246 struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer);
247 struct xlib_brw_winsys *xbw = xlib_brw_winsys(buffer->sws);
248 unsigned i;
249
250 if (BRW_DEBUG & DEBUG_WINSYS)
251 debug_printf("%s buf %p off %d sz %d %s relocs: %d\n",
252 __FUNCTION__,
253 (void *)buffer, offset, size,
254 data_types[data_type],
255 nr_relocs);
256
257 assert(buf->base.size >= offset + size);
258 memcpy(buf->virtual + offset, data, size);
259
260 /* Apply the relocations:
261 */
262 for (i = 0; i < nr_relocs; i++) {
263 if (BRW_DEBUG & DEBUG_WINSYS)
264 debug_printf("\treloc[%d] usage %s off %d value %x+%x\n",
265 i, usages[reloc[i].usage], reloc[i].offset,
266 xlib_brw_buffer(reloc[i].bo)->offset, reloc[i].delta);
267
268 *(unsigned *)(buf->virtual + offset + reloc[i].offset) =
269 xlib_brw_buffer(reloc[i].bo)->offset + reloc[i].delta;
270 }
271
272 if (BRW_DUMP)
273 brw_dump_data( xbw->chipset.pci_id,
274 data_type,
275 buf->offset + offset,
276 buf->virtual + offset, size );
277
278
279 return 0;
280 }
281
282
283 static boolean
284 xlib_brw_bo_is_busy(struct brw_winsys_buffer *buffer)
285 {
286 if (BRW_DEBUG & DEBUG_WINSYS)
287 debug_printf("%s %p\n", __FUNCTION__, (void *)buffer);
288 return TRUE;
289 }
290
291 static boolean
292 xlib_brw_bo_references(struct brw_winsys_buffer *a,
293 struct brw_winsys_buffer *b)
294 {
295 if (BRW_DEBUG & DEBUG_WINSYS)
296 debug_printf("%s %p %p\n", __FUNCTION__, (void *)a, (void *)b);
297 return TRUE;
298 }
299
300 static enum pipe_error
301 xlib_brw_check_aperture_space( struct brw_winsys_screen *iws,
302 struct brw_winsys_buffer **buffers,
303 unsigned count )
304 {
305 unsigned tot_size = 0;
306 unsigned i;
307
308 for (i = 0; i < count; i++)
309 tot_size += buffers[i]->size;
310
311 if (BRW_DEBUG & DEBUG_WINSYS)
312 debug_printf("%s %d bufs, tot_size: %d kb\n",
313 __FUNCTION__, count,
314 (tot_size + 1023) / 1024);
315
316 return PIPE_OK;
317 }
318
319 static void *
320 xlib_brw_bo_map(struct brw_winsys_buffer *buffer,
321 enum brw_buffer_data_type data_type,
322 unsigned offset,
323 unsigned length,
324 boolean write,
325 boolean discard,
326 boolean explicit)
327 {
328 struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer);
329
330 if (BRW_DEBUG & DEBUG_WINSYS)
331 debug_printf("%s %p %s %s\n", __FUNCTION__, (void *)buffer,
332 write ? "read/write" : "read",
333 write ? data_types[data_type] : "");
334
335 if (write)
336 buf->modified = 1;
337
338 buf->map_count++;
339 return buf->virtual;
340 }
341
342
343 static void
344 xlib_brw_bo_flush_range( struct brw_winsys_buffer *buffer,
345 unsigned offset,
346 unsigned length )
347 {
348 }
349
350
351 static void
352 xlib_brw_bo_unmap(struct brw_winsys_buffer *buffer)
353 {
354 struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer);
355
356 if (BRW_DEBUG & DEBUG_WINSYS)
357 debug_printf("%s %p\n", __FUNCTION__, (void *)buffer);
358
359 --buf->map_count;
360 assert(buf->map_count >= 0);
361
362 if (buf->map_count == 0 &&
363 buf->modified) {
364
365 buf->modified = 0;
366
367 /* Consider dumping new buffer contents here, using the
368 * flush-range info to minimize verbosity.
369 */
370 }
371 }
372
373
374 static void
375 xlib_brw_bo_wait_idle( struct brw_winsys_buffer *buffer )
376 {
377 }
378
379
380 static void
381 xlib_brw_winsys_destroy( struct brw_winsys_screen *sws )
382 {
383 struct xlib_brw_winsys *xbw = xlib_brw_winsys(sws);
384
385 FREE(xbw);
386 }
387
388 static struct brw_winsys_screen *
389 xlib_create_brw_winsys_screen( void )
390 {
391 struct xlib_brw_winsys *ws;
392
393 ws = CALLOC_STRUCT(xlib_brw_winsys);
394 if (!ws)
395 return NULL;
396
397 ws->used = 0;
398
399 ws->base.destroy = xlib_brw_winsys_destroy;
400 ws->base.bo_alloc = xlib_brw_bo_alloc;
401 ws->base.bo_destroy = xlib_brw_bo_destroy;
402 ws->base.bo_emit_reloc = xlib_brw_bo_emit_reloc;
403 ws->base.bo_exec = xlib_brw_bo_exec;
404 ws->base.bo_subdata = xlib_brw_bo_subdata;
405 ws->base.bo_is_busy = xlib_brw_bo_is_busy;
406 ws->base.bo_references = xlib_brw_bo_references;
407 ws->base.check_aperture_space = xlib_brw_check_aperture_space;
408 ws->base.bo_map = xlib_brw_bo_map;
409 ws->base.bo_flush_range = xlib_brw_bo_flush_range;
410 ws->base.bo_unmap = xlib_brw_bo_unmap;
411 ws->base.bo_wait_idle = xlib_brw_bo_wait_idle;
412
413 return &ws->base;
414 }
415
416
417 /***********************************************************************
418 * Implementation of Xlib co-state-tracker's winsys interface
419 */
420
421 static void
422 xlib_i965_display_surface(struct xmesa_buffer *xm_buffer,
423 struct pipe_surface *surf)
424 {
425 struct brw_surface *surface = brw_surface(surf);
426 struct xlib_brw_buffer *bo = xlib_brw_buffer(surface->bo);
427
428 if (BRW_DEBUG & DEBUG_WINSYS)
429 debug_printf("%s offset %x+%x sz %dx%d\n", __FUNCTION__,
430 bo->offset,
431 surface->draw_offset,
432 surf->width,
433 surf->height);
434 }
435
436 static void
437 xlib_i965_flush_frontbuffer(struct pipe_screen *screen,
438 struct pipe_surface *surf,
439 void *context_private)
440 {
441 xlib_i965_display_surface(NULL, surf);
442 }
443
444
445 static struct pipe_screen *
446 xlib_create_i965_screen( void )
447 {
448 struct brw_winsys_screen *winsys;
449 struct pipe_screen *screen;
450
451 winsys = xlib_create_brw_winsys_screen();
452 if (winsys == NULL)
453 return NULL;
454
455 screen = brw_create_screen(winsys, PCI_CHIP_GM45_GM);
456 if (screen == NULL)
457 goto fail;
458
459 xlib_brw_winsys(winsys)->chipset = brw_screen(screen)->chipset;
460
461 screen->flush_frontbuffer = xlib_i965_flush_frontbuffer;
462 return screen;
463
464 fail:
465 if (winsys)
466 winsys->destroy( winsys );
467
468 return NULL;
469 }
470
471
472
473
474
475 struct xm_driver xlib_i965_driver =
476 {
477 .create_pipe_screen = xlib_create_i965_screen,
478 .display_surface = xlib_i965_display_surface
479 };
480
481
482 /* Register this driver at library load:
483 */
484 static void _init( void ) __attribute__((constructor));
485 static void _init( void )
486 {
487 xmesa_set_driver( &xlib_i965_driver );
488 }
489
490
491
492 /***********************************************************************
493 *
494 * Butt-ugly hack to convince the linker not to throw away public GL
495 * symbols (they are all referenced from getprocaddress, I guess).
496 */
497 extern void (*linker_foo(const unsigned char *procName))();
498 extern void (*glXGetProcAddress(const unsigned char *procName))();
499
500 extern void (*linker_foo(const unsigned char *procName))()
501 {
502 return glXGetProcAddress(procName);
503 }