1/**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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 above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include <stdio.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <errno.h>
32#include <signal.h>
33#include <fcntl.h>
34#include <dirent.h>
35#include <string.h>
36#include <assert.h>
37
38#include <sys/ioctl.h>
39#include <X11/Xlibint.h>
40#include <fourcc.h>
41#include <X11/extensions/Xv.h>
42#include <X11/extensions/Xvlib.h>
43#include <X11/extensions/XvMC.h>
44#include <X11/extensions/XvMClib.h>
45
46#include "intel_xvmc.h"
47#include "intel_batchbuffer.h"
48#include "brw_defines.h"
49#include "brw_structs.h"
50#define MI_BATCH_BUFFER_END     (0xA << 23)
51#define BATCH_SIZE 8*1024 /* one bo is allocated each time, so the size can be small */
52static int intelEmitIrqLocked(void)
53{
54   drmI830IrqEmit ie;
55   int ret, seq;
56
57   ie.irq_seq = &seq;
58   ret = drmCommandWriteRead(xvmc_driver->fd, DRM_I830_IRQ_EMIT,
59                             &ie, sizeof(ie));
60
61   if ( ret ) {
62      fprintf(stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret);
63      exit(1);
64   }
65
66   return seq;
67}
68
69static void intelWaitIrq(int seq)
70{
71   int ret;
72   drmI830IrqWait iw;
73
74   iw.irq_seq = seq;
75
76   do {
77      ret = drmCommandWrite(xvmc_driver->fd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) );
78   } while (ret == -EAGAIN || ret == -EINTR);
79
80   if (ret) {
81      fprintf(stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret);
82      exit(1);
83   }
84}
85
86static void i965_end_batch(void)
87{
88    unsigned int size = xvmc_driver->batch.ptr -
89	xvmc_driver->batch.init_ptr;
90    if ((size & 4) == 0) {
91	*(unsigned int*)xvmc_driver->batch.ptr = 0;
92	xvmc_driver->batch.ptr += 4;
93    }
94    *(unsigned int*)xvmc_driver->batch.ptr = MI_BATCH_BUFFER_END;
95    xvmc_driver->batch.ptr += 4;
96}
97
98Bool intelInitBatchBuffer(void)
99{
100    int i;
101
102    if((xvmc_driver->batch.buf =
103		drm_intel_bo_alloc(xvmc_driver->bufmgr,
104		    "batch buffer", BATCH_SIZE, 0x1000)) == NULL) {
105	fprintf(stderr, "unable to alloc batch buffer\n");
106	return False;
107    }
108
109    if (xvmc_driver->kernel_exec_fencing)
110        drm_intel_gem_bo_map_gtt(xvmc_driver->batch.buf);
111    else
112        drm_intel_bo_map(xvmc_driver->batch.buf, 1);
113
114    xvmc_driver->batch.init_ptr = xvmc_driver->batch.buf->virtual;
115    xvmc_driver->batch.size = BATCH_SIZE;
116    xvmc_driver->batch.space = BATCH_SIZE;
117    xvmc_driver->batch.ptr = xvmc_driver->batch.init_ptr;
118    return True;
119}
120
121void intelFiniBatchBuffer(void)
122{
123    if (xvmc_driver->kernel_exec_fencing)
124        drm_intel_gem_bo_unmap_gtt(xvmc_driver->batch.buf);
125    else
126        drm_intel_bo_unmap(xvmc_driver->batch.buf);
127
128    drm_intel_bo_unreference(xvmc_driver->batch.buf);
129}
130
131
132void intelFlushBatch(Bool refill )
133{
134    i965_end_batch();
135
136    if (xvmc_driver->kernel_exec_fencing)
137        drm_intel_gem_bo_unmap_gtt(xvmc_driver->batch.buf);
138    else
139        drm_intel_bo_unmap(xvmc_driver->batch.buf);
140
141    drm_intel_bo_exec(xvmc_driver->batch.buf,
142	    xvmc_driver->batch.ptr - xvmc_driver->batch.init_ptr,
143	    0, 0, 0);
144
145    if (xvmc_driver == &i915_xvmc_mc_driver)
146	    dri_bo_wait_rendering(xvmc_driver->batch.buf);
147
148    drm_intel_bo_unreference(xvmc_driver->batch.buf);
149    if((xvmc_driver->batch.buf =
150		drm_intel_bo_alloc(xvmc_driver->bufmgr,
151		    "batch buffer", BATCH_SIZE, 0x1000)) == NULL) {
152	fprintf(stderr, "unable to alloc batch buffer\n");
153    }
154
155    if (xvmc_driver->kernel_exec_fencing)
156        drm_intel_gem_bo_map_gtt(xvmc_driver->batch.buf);
157    else
158        drm_intel_bo_map(xvmc_driver->batch.buf, 1);
159
160    xvmc_driver->batch.init_ptr = xvmc_driver->batch.buf->virtual;
161    xvmc_driver->batch.size = BATCH_SIZE;
162    xvmc_driver->batch.space = BATCH_SIZE;
163    xvmc_driver->batch.ptr = xvmc_driver->batch.init_ptr;
164}
165
166void intelBatchbufferRequireSpace(int size)
167{
168    assert(xvmc_driver->batch.ptr - xvmc_driver->batch.init_ptr + size <
169        xvmc_driver->batch.size - 8);
170    if (xvmc_driver->batch.ptr - xvmc_driver->batch.init_ptr + size
171	    >= xvmc_driver->batch.size - 8)
172	intelFlushBatch(1);
173}
174
175void intelBatchbufferData(const void *data, unsigned bytes, unsigned flags)
176{
177   intelBatchbufferRequireSpace(bytes);
178   memcpy(xvmc_driver->batch.ptr, data, bytes);
179   xvmc_driver->batch.ptr += bytes;
180   xvmc_driver->batch.space -= bytes;
181}
182
183void intel_batch_emit_reloc(dri_bo *bo, uint32_t read_domain,
184	uint32_t write_domain, uint32_t delta, unsigned char *ptr)
185{
186    drm_intel_bo_emit_reloc(xvmc_driver->batch.buf,
187	    ptr - xvmc_driver->batch.init_ptr, bo, delta,
188	    read_domain, write_domain);
189}
190