nouveau: reindent nouveau_buffers.h
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_buffers.c
1 #include "utils.h"
2 #include "framebuffer.h"
3 #include "renderbuffer.h"
4 #include "fbobject.h"
5
6 #include "nouveau_context.h"
7 #include "nouveau_buffers.h"
8 #include "nouveau_object.h"
9 #include "nouveau_fifo.h"
10 #include "nouveau_reg.h"
11 #include "nouveau_msg.h"
12
13 #define MAX_MEMFMT_LENGTH 32768
14
15 /* Unstrided blit using NV_MEMORY_TO_MEMORY_FORMAT */
16 GLboolean
17 nouveau_memformat_flat_emit(GLcontext * ctx,
18 nouveau_mem * dst, nouveau_mem * src,
19 GLuint dst_offset, GLuint src_offset,
20 GLuint size)
21 {
22 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
23 uint32_t src_handle, dst_handle;
24 GLuint count;
25
26 if (src_offset + size > src->size) {
27 MESSAGE("src out of nouveau_mem bounds\n");
28 return GL_FALSE;
29 }
30 if (dst_offset + size > dst->size) {
31 MESSAGE("dst out of nouveau_mem bounds\n");
32 return GL_FALSE;
33 }
34
35 src_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT;
36 dst_handle = (dst->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT;
37 src_offset += nouveau_mem_gpu_offset_get(ctx, src);
38 dst_offset += nouveau_mem_gpu_offset_get(ctx, dst);
39
40 BEGIN_RING_SIZE(NvSubMemFormat,
41 NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN, 2);
42 OUT_RING(src_handle);
43 OUT_RING(dst_handle);
44
45 count = (size / MAX_MEMFMT_LENGTH) +
46 ((size % MAX_MEMFMT_LENGTH) ? 1 : 0);
47
48 while (count--) {
49 GLuint length =
50 (size > MAX_MEMFMT_LENGTH) ? MAX_MEMFMT_LENGTH : size;
51
52 BEGIN_RING_SIZE(NvSubMemFormat,
53 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
54 OUT_RING(src_offset);
55 OUT_RING(dst_offset);
56 OUT_RING(0); /* pitch in */
57 OUT_RING(0); /* pitch out */
58 OUT_RING(length); /* line length */
59 OUT_RING(1); /* number of lines */
60 OUT_RING((1 << 8) /* dst_inc */ |(1 << 0) /* src_inc */ );
61 OUT_RING(0); /* buffer notify? */
62 FIRE_RING();
63
64 src_offset += length;
65 dst_offset += length;
66 size -= length;
67 }
68
69 return GL_TRUE;
70 }
71
72 void nouveau_mem_free(GLcontext * ctx, nouveau_mem * mem)
73 {
74 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
75 struct drm_nouveau_mem_free memf;
76
77 if (NOUVEAU_DEBUG & DEBUG_MEM) {
78 fprintf(stderr, "%s: type=0x%x, offset=0x%x, size=0x%x\n",
79 __func__, mem->type, (GLuint) mem->offset,
80 (GLuint) mem->size);
81 }
82
83 if (mem->map)
84 drmUnmap(mem->map, mem->size);
85 memf.flags = mem->type;
86 memf.offset = mem->offset;
87 drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_MEM_FREE, &memf,
88 sizeof(memf));
89 FREE(mem);
90 }
91
92 nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, uint32_t flags, GLuint size,
93 GLuint align)
94 {
95 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
96 struct drm_nouveau_mem_alloc mema;
97 nouveau_mem *mem;
98 int ret;
99
100 if (NOUVEAU_DEBUG & DEBUG_MEM) {
101 fprintf(stderr,
102 "%s: requested: flags=0x%x, size=0x%x, align=0x%x\n",
103 __func__, flags, (GLuint) size, align);
104 }
105
106 mem = CALLOC(sizeof(nouveau_mem));
107 if (!mem)
108 return NULL;
109
110 mema.flags = flags;
111 mema.size = mem->size = size;
112 mema.alignment = align;
113 mem->map = NULL;
114 ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC,
115 &mema, sizeof(mema));
116 if (ret) {
117 FREE(mem);
118 return NULL;
119 }
120 mem->offset = mema.offset;
121 mem->type = mema.flags;
122
123 if (NOUVEAU_DEBUG & DEBUG_MEM) {
124 fprintf(stderr,
125 "%s: actual: type=0x%x, offset=0x%x, size=0x%x\n",
126 __func__, mem->type, (GLuint) mem->offset,
127 (GLuint) mem->size);
128 }
129
130 if (flags & NOUVEAU_MEM_MAPPED)
131 ret = drmMap(nmesa->driFd, mema.map_handle, mem->size,
132 &mem->map);
133 if (ret) {
134 mem->map = NULL;
135 nouveau_mem_free(ctx, mem);
136 mem = NULL;
137 }
138
139 return mem;
140 }
141
142 uint32_t nouveau_mem_gpu_offset_get(GLcontext * ctx, nouveau_mem * mem)
143 {
144 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
145
146 return mem->offset;
147 }
148
149 static GLboolean
150 nouveau_renderbuffer_pixelformat(nouveau_renderbuffer * nrb,
151 GLenum internalFormat)
152 {
153 nrb->mesa.InternalFormat = internalFormat;
154
155 /*TODO: We probably want to extend this a bit, and maybe make
156 * card-specific?
157 */
158 switch (internalFormat) {
159 case GL_RGBA:
160 case GL_RGBA8:
161 nrb->mesa._BaseFormat = GL_RGBA;
162 nrb->mesa._ActualFormat = GL_RGBA8;
163 nrb->mesa.DataType = GL_UNSIGNED_BYTE;
164 nrb->mesa.RedBits = 8;
165 nrb->mesa.GreenBits = 8;
166 nrb->mesa.BlueBits = 8;
167 nrb->mesa.AlphaBits = 8;
168 nrb->cpp = 4;
169 break;
170 case GL_RGB:
171 case GL_RGB5:
172 nrb->mesa._BaseFormat = GL_RGB;
173 nrb->mesa._ActualFormat = GL_RGB5;
174 nrb->mesa.DataType = GL_UNSIGNED_BYTE;
175 nrb->mesa.RedBits = 5;
176 nrb->mesa.GreenBits = 6;
177 nrb->mesa.BlueBits = 5;
178 nrb->mesa.AlphaBits = 0;
179 nrb->cpp = 2;
180 break;
181 case GL_DEPTH_COMPONENT16:
182 nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT;
183 nrb->mesa._ActualFormat = GL_DEPTH_COMPONENT16;
184 nrb->mesa.DataType = GL_UNSIGNED_SHORT;
185 nrb->mesa.DepthBits = 16;
186 nrb->cpp = 2;
187 break;
188 case GL_DEPTH_COMPONENT24:
189 nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT;
190 nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
191 nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
192 nrb->mesa.DepthBits = 24;
193 nrb->cpp = 4;
194 break;
195 case GL_STENCIL_INDEX8_EXT:
196 nrb->mesa._BaseFormat = GL_STENCIL_INDEX;
197 nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
198 nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
199 nrb->mesa.StencilBits = 8;
200 nrb->cpp = 4;
201 break;
202 case GL_DEPTH24_STENCIL8_EXT:
203 nrb->mesa._BaseFormat = GL_DEPTH_STENCIL_EXT;
204 nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT;
205 nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT;
206 nrb->mesa.DepthBits = 24;
207 nrb->mesa.StencilBits = 8;
208 nrb->cpp = 4;
209 break;
210 default:
211 return GL_FALSE;
212 break;
213 }
214
215 return GL_TRUE;
216 }
217
218 static GLboolean
219 nouveau_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
220 GLenum internalFormat,
221 GLuint width, GLuint height)
222 {
223 nouveau_renderbuffer *nrb = (nouveau_renderbuffer *) rb;
224
225 if (!nouveau_renderbuffer_pixelformat(nrb, internalFormat)) {
226 fprintf(stderr, "%s: unknown internalFormat\n", __func__);
227 return GL_FALSE;
228 }
229
230 /* If this buffer isn't statically alloc'd, we may need to ask the
231 * drm for more memory */
232 if (!nrb->dPriv && (rb->Width != width || rb->Height != height)) {
233 GLuint pitch;
234
235 /* align pitches to 64 bytes */
236 pitch = ((width * nrb->cpp) + 63) & ~63;
237
238 if (nrb->mem)
239 nouveau_mem_free(ctx, nrb->mem);
240 nrb->mem = nouveau_mem_alloc(ctx,
241 NOUVEAU_MEM_FB |
242 NOUVEAU_MEM_MAPPED,
243 pitch * height, 0);
244 if (!nrb->mem)
245 return GL_FALSE;
246
247 /* update nouveau_renderbuffer info */
248 nrb->offset = nouveau_mem_gpu_offset_get(ctx, nrb->mem);
249 nrb->pitch = pitch;
250 }
251
252 rb->Width = width;
253 rb->Height = height;
254 rb->InternalFormat = internalFormat;
255 return GL_TRUE;
256 }
257
258 static void nouveau_renderbuffer_delete(struct gl_renderbuffer *rb)
259 {
260 GET_CURRENT_CONTEXT(ctx);
261 nouveau_renderbuffer *nrb = (nouveau_renderbuffer *) rb;
262
263 if (nrb->mem)
264 nouveau_mem_free(ctx, nrb->mem);
265 FREE(nrb);
266 }
267
268 nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat,
269 GLvoid * map, GLuint offset,
270 GLuint pitch,
271 __DRIdrawablePrivate *
272 dPriv)
273 {
274 nouveau_renderbuffer *nrb;
275
276 nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
277 if (nrb) {
278 _mesa_init_renderbuffer(&nrb->mesa, 0);
279
280 nouveau_renderbuffer_pixelformat(nrb, internalFormat);
281
282 nrb->mesa.AllocStorage = nouveau_renderbuffer_storage;
283 nrb->mesa.Delete = nouveau_renderbuffer_delete;
284
285 nrb->dPriv = dPriv;
286 nrb->offset = offset;
287 nrb->pitch = pitch;
288 nrb->map = map;
289 }
290
291 return nrb;
292 }
293
294 static void
295 nouveau_cliprects_drawable_set(nouveauContextPtr nmesa,
296 nouveau_renderbuffer * nrb)
297 {
298 __DRIdrawablePrivate *dPriv = nrb->dPriv;
299
300 nmesa->numClipRects = dPriv->numClipRects;
301 nmesa->pClipRects = dPriv->pClipRects;
302 nmesa->drawX = dPriv->x;
303 nmesa->drawY = dPriv->y;
304 nmesa->drawW = dPriv->w;
305 nmesa->drawH = dPriv->h;
306 }
307
308 static void
309 nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa,
310 nouveau_renderbuffer * nrb)
311 {
312 nmesa->numClipRects = 1;
313 nmesa->pClipRects = &nmesa->osClipRect;
314 nmesa->osClipRect.x1 = 0;
315 nmesa->osClipRect.y1 = 0;
316 nmesa->osClipRect.x2 = nrb->mesa.Width;
317 nmesa->osClipRect.y2 = nrb->mesa.Height;
318 nmesa->drawX = 0;
319 nmesa->drawY = 0;
320 nmesa->drawW = nrb->mesa.Width;
321 nmesa->drawH = nrb->mesa.Height;
322 }
323
324 void nouveau_window_moved(GLcontext * ctx)
325 {
326 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
327 nouveau_renderbuffer *nrb;
328
329 nrb = (nouveau_renderbuffer *)ctx->DrawBuffer->_ColorDrawBuffers[0][0];
330 if (!nrb)
331 return;
332
333 if (!nrb->dPriv)
334 nouveau_cliprects_renderbuffer_set(nmesa, nrb);
335 else
336 nouveau_cliprects_drawable_set(nmesa, nrb);
337
338 /* Viewport depends on window size/position, nouveauCalcViewport
339 * will take care of calling the hw-specific WindowMoved
340 */
341 ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y,
342 ctx->Viewport.Width, ctx->Viewport.Height);
343 /* Scissor depends on window position */
344 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
345 ctx->Scissor.Width, ctx->Scissor.Height);
346 }
347
348 GLboolean
349 nouveau_build_framebuffer(GLcontext * ctx, struct gl_framebuffer *fb)
350 {
351 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
352 nouveau_renderbuffer *color[MAX_DRAW_BUFFERS];
353 nouveau_renderbuffer *depth;
354
355 _mesa_update_framebuffer(ctx);
356 _mesa_update_draw_buffer_bounds(ctx);
357
358 color[0] = (nouveau_renderbuffer *) fb->_ColorDrawBuffers[0][0];
359 if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped)
360 depth = (nouveau_renderbuffer *) fb->_DepthBuffer->Wrapped;
361 else
362 depth = (nouveau_renderbuffer *) fb->_DepthBuffer;
363
364 if (!nmesa->hw_func.BindBuffers(nmesa, 1, color, depth))
365 return GL_FALSE;
366 nouveau_window_moved(ctx);
367
368 return GL_TRUE;
369 }
370
371 static void nouveauDrawBuffer(GLcontext * ctx, GLenum buffer)
372 {
373 nouveau_build_framebuffer(ctx, ctx->DrawBuffer);
374 }
375
376 static struct gl_framebuffer *nouveauNewFramebuffer(GLcontext * ctx,
377 GLuint name)
378 {
379 return _mesa_new_framebuffer(ctx, name);
380 }
381
382 static struct gl_renderbuffer *nouveauNewRenderbuffer(GLcontext * ctx,
383 GLuint name)
384 {
385 nouveau_renderbuffer *nrb;
386
387 nrb = CALLOC_STRUCT(nouveau_renderbuffer_t);
388 if (nrb) {
389 _mesa_init_renderbuffer(&nrb->mesa, name);
390
391 nrb->mesa.AllocStorage = nouveau_renderbuffer_storage;
392 nrb->mesa.Delete = nouveau_renderbuffer_delete;
393 }
394 return &nrb->mesa;
395 }
396
397 static void
398 nouveauBindFramebuffer(GLcontext * ctx, GLenum target,
399 struct gl_framebuffer *fb,
400 struct gl_framebuffer *fbread)
401 {
402 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) {
403 nouveau_build_framebuffer(ctx, fb);
404 }
405 }
406
407 static void
408 nouveauFramebufferRenderbuffer(GLcontext * ctx,
409 struct gl_framebuffer *fb,
410 GLenum attachment,
411 struct gl_renderbuffer *rb)
412 {
413 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
414 nouveau_build_framebuffer(ctx, fb);
415 }
416
417 static void
418 nouveauRenderTexture(GLcontext * ctx,
419 struct gl_framebuffer *fb,
420 struct gl_renderbuffer_attachment *att)
421 {
422 }
423
424 static void
425 nouveauFinishRenderTexture(GLcontext * ctx,
426 struct gl_renderbuffer_attachment *att)
427 {
428 }
429
430 void nouveauInitBufferFuncs(struct dd_function_table *func)
431 {
432 func->DrawBuffer = nouveauDrawBuffer;
433
434 func->NewFramebuffer = nouveauNewFramebuffer;
435 func->NewRenderbuffer = nouveauNewRenderbuffer;
436 func->BindFramebuffer = nouveauBindFramebuffer;
437 func->FramebufferRenderbuffer = nouveauFramebufferRenderbuffer;
438 func->RenderTexture = nouveauRenderTexture;
439 func->FinishRenderTexture = nouveauFinishRenderTexture;
440 }