2 #include "framebuffer.h"
3 #include "renderbuffer.h"
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"
13 #define MAX_MEMFMT_LENGTH 32768
15 /* Unstrided blit using NV_MEMORY_TO_MEMORY_FORMAT */
17 nouveau_memformat_flat_emit(GLcontext
* ctx
,
18 nouveau_mem
* dst
, nouveau_mem
* src
,
19 GLuint dst_offset
, GLuint src_offset
,
22 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
23 uint32_t src_handle
, dst_handle
;
26 if (src_offset
+ size
> src
->size
) {
27 MESSAGE("src out of nouveau_mem bounds\n");
30 if (dst_offset
+ size
> dst
->size
) {
31 MESSAGE("dst out of nouveau_mem bounds\n");
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
);
40 BEGIN_RING_SIZE(NvSubMemFormat
,
41 NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN
, 2);
45 count
= (size
/ MAX_MEMFMT_LENGTH
) +
46 ((size
% MAX_MEMFMT_LENGTH
) ? 1 : 0);
50 (size
> MAX_MEMFMT_LENGTH
) ? MAX_MEMFMT_LENGTH
: size
;
52 BEGIN_RING_SIZE(NvSubMemFormat
,
53 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
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? */
72 void nouveau_mem_free(GLcontext
* ctx
, nouveau_mem
* mem
)
74 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
75 struct drm_nouveau_mem_free memf
;
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
,
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
,
92 nouveau_mem
*nouveau_mem_alloc(GLcontext
*ctx
, uint32_t flags
, GLuint size
,
95 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
96 struct drm_nouveau_mem_alloc mema
;
100 if (NOUVEAU_DEBUG
& DEBUG_MEM
) {
102 "%s: requested: flags=0x%x, size=0x%x, align=0x%x\n",
103 __func__
, flags
, (GLuint
) size
, align
);
106 mem
= CALLOC(sizeof(nouveau_mem
));
111 mema
.size
= mem
->size
= size
;
112 mema
.alignment
= align
;
114 ret
= drmCommandWriteRead(nmesa
->driFd
, DRM_NOUVEAU_MEM_ALLOC
,
115 &mema
, sizeof(mema
));
120 mem
->offset
= mema
.offset
;
121 mem
->type
= mema
.flags
;
123 if (NOUVEAU_DEBUG
& DEBUG_MEM
) {
125 "%s: actual: type=0x%x, offset=0x%x, size=0x%x\n",
126 __func__
, mem
->type
, (GLuint
) mem
->offset
,
130 if (flags
& NOUVEAU_MEM_MAPPED
)
131 ret
= drmMap(nmesa
->driFd
, mema
.map_handle
, mem
->size
,
135 nouveau_mem_free(ctx
, mem
);
142 uint32_t nouveau_mem_gpu_offset_get(GLcontext
* ctx
, nouveau_mem
* mem
)
144 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
150 nouveau_renderbuffer_pixelformat(nouveau_renderbuffer
* nrb
,
151 GLenum internalFormat
)
153 nrb
->mesa
.InternalFormat
= internalFormat
;
155 /*TODO: We probably want to extend this a bit, and maybe make
158 switch (internalFormat
) {
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;
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;
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;
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;
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;
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;
219 nouveau_renderbuffer_storage(GLcontext
* ctx
, struct gl_renderbuffer
*rb
,
220 GLenum internalFormat
,
221 GLuint width
, GLuint height
)
223 nouveau_renderbuffer
*nrb
= (nouveau_renderbuffer
*) rb
;
225 if (!nouveau_renderbuffer_pixelformat(nrb
, internalFormat
)) {
226 fprintf(stderr
, "%s: unknown internalFormat\n", __func__
);
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
)) {
235 /* align pitches to 64 bytes */
236 pitch
= ((width
* nrb
->cpp
) + 63) & ~63;
239 nouveau_mem_free(ctx
, nrb
->mem
);
240 nrb
->mem
= nouveau_mem_alloc(ctx
,
247 /* update nouveau_renderbuffer info */
248 nrb
->offset
= nouveau_mem_gpu_offset_get(ctx
, nrb
->mem
);
254 rb
->InternalFormat
= internalFormat
;
258 static void nouveau_renderbuffer_delete(struct gl_renderbuffer
*rb
)
260 GET_CURRENT_CONTEXT(ctx
);
261 nouveau_renderbuffer
*nrb
= (nouveau_renderbuffer
*) rb
;
264 nouveau_mem_free(ctx
, nrb
->mem
);
268 nouveau_renderbuffer
*nouveau_renderbuffer_new(GLenum internalFormat
,
269 GLvoid
* map
, GLuint offset
,
271 __DRIdrawablePrivate
*
274 nouveau_renderbuffer
*nrb
;
276 nrb
= CALLOC_STRUCT(nouveau_renderbuffer_t
);
278 _mesa_init_renderbuffer(&nrb
->mesa
, 0);
280 nouveau_renderbuffer_pixelformat(nrb
, internalFormat
);
282 nrb
->mesa
.AllocStorage
= nouveau_renderbuffer_storage
;
283 nrb
->mesa
.Delete
= nouveau_renderbuffer_delete
;
286 nrb
->offset
= offset
;
295 nouveau_cliprects_drawable_set(nouveauContextPtr nmesa
,
296 nouveau_renderbuffer
* nrb
)
298 __DRIdrawablePrivate
*dPriv
= nrb
->dPriv
;
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
;
309 nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa
,
310 nouveau_renderbuffer
* nrb
)
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
;
320 nmesa
->drawW
= nrb
->mesa
.Width
;
321 nmesa
->drawH
= nrb
->mesa
.Height
;
324 void nouveau_window_moved(GLcontext
* ctx
)
326 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
327 nouveau_renderbuffer
*nrb
;
329 nrb
= (nouveau_renderbuffer
*)ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
334 nouveau_cliprects_renderbuffer_set(nmesa
, nrb
);
336 nouveau_cliprects_drawable_set(nmesa
, nrb
);
338 /* Viewport depends on window size/position, nouveauCalcViewport
339 * will take care of calling the hw-specific WindowMoved
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
);
349 nouveau_build_framebuffer(GLcontext
* ctx
, struct gl_framebuffer
*fb
)
351 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
352 nouveau_renderbuffer
*color
[MAX_DRAW_BUFFERS
];
353 nouveau_renderbuffer
*depth
;
355 _mesa_update_framebuffer(ctx
);
356 _mesa_update_draw_buffer_bounds(ctx
);
358 color
[0] = (nouveau_renderbuffer
*) fb
->_ColorDrawBuffers
[0][0];
359 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
)
360 depth
= (nouveau_renderbuffer
*) fb
->_DepthBuffer
->Wrapped
;
362 depth
= (nouveau_renderbuffer
*) fb
->_DepthBuffer
;
364 if (!nmesa
->hw_func
.BindBuffers(nmesa
, 1, color
, depth
))
366 nouveau_window_moved(ctx
);
371 static void nouveauDrawBuffer(GLcontext
* ctx
, GLenum buffer
)
373 nouveau_build_framebuffer(ctx
, ctx
->DrawBuffer
);
376 static struct gl_framebuffer
*nouveauNewFramebuffer(GLcontext
* ctx
,
379 return _mesa_new_framebuffer(ctx
, name
);
382 static struct gl_renderbuffer
*nouveauNewRenderbuffer(GLcontext
* ctx
,
385 nouveau_renderbuffer
*nrb
;
387 nrb
= CALLOC_STRUCT(nouveau_renderbuffer_t
);
389 _mesa_init_renderbuffer(&nrb
->mesa
, name
);
391 nrb
->mesa
.AllocStorage
= nouveau_renderbuffer_storage
;
392 nrb
->mesa
.Delete
= nouveau_renderbuffer_delete
;
398 nouveauBindFramebuffer(GLcontext
* ctx
, GLenum target
,
399 struct gl_framebuffer
*fb
,
400 struct gl_framebuffer
*fbread
)
402 if (target
== GL_FRAMEBUFFER_EXT
|| target
== GL_DRAW_FRAMEBUFFER_EXT
) {
403 nouveau_build_framebuffer(ctx
, fb
);
408 nouveauFramebufferRenderbuffer(GLcontext
* ctx
,
409 struct gl_framebuffer
*fb
,
411 struct gl_renderbuffer
*rb
)
413 _mesa_framebuffer_renderbuffer(ctx
, fb
, attachment
, rb
);
414 nouveau_build_framebuffer(ctx
, fb
);
418 nouveauRenderTexture(GLcontext
* ctx
,
419 struct gl_framebuffer
*fb
,
420 struct gl_renderbuffer_attachment
*att
)
425 nouveauFinishRenderTexture(GLcontext
* ctx
,
426 struct gl_renderbuffer_attachment
*att
)
430 void nouveauInitBufferFuncs(struct dd_function_table
*func
)
432 func
->DrawBuffer
= nouveauDrawBuffer
;
434 func
->NewFramebuffer
= nouveauNewFramebuffer
;
435 func
->NewRenderbuffer
= nouveauNewRenderbuffer
;
436 func
->BindFramebuffer
= nouveauBindFramebuffer
;
437 func
->FramebufferRenderbuffer
= nouveauFramebufferRenderbuffer
;
438 func
->RenderTexture
= nouveauRenderTexture
;
439 func
->FinishRenderTexture
= nouveauFinishRenderTexture
;