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
, NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN
, 2);
41 OUT_RING (src_handle
);
42 OUT_RING (dst_handle
);
44 count
= (size
/ MAX_MEMFMT_LENGTH
) + ((size
% MAX_MEMFMT_LENGTH
) ? 1 : 0);
47 GLuint length
= (size
> MAX_MEMFMT_LENGTH
) ? MAX_MEMFMT_LENGTH
: size
;
49 BEGIN_RING_SIZE(NvSubMemFormat
, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
50 OUT_RING (src_offset
);
51 OUT_RING (dst_offset
);
52 OUT_RING (0); /* pitch in */
53 OUT_RING (0); /* pitch out */
54 OUT_RING (length
); /* line length */
55 OUT_RING (1); /* number of lines */
56 OUT_RING ((1 << 8) /* dst_inc */ | (1 << 0) /* src_inc */);
57 OUT_RING (0); /* buffer notify? */
69 nouveau_mem_free(GLcontext
*ctx
, nouveau_mem
*mem
)
71 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
72 struct drm_nouveau_mem_free memf
;
74 if (NOUVEAU_DEBUG
& DEBUG_MEM
) {
75 fprintf(stderr
, "%s: type=0x%x, offset=0x%x, size=0x%x\n",
76 __func__
, mem
->type
, (GLuint
)mem
->offset
, (GLuint
)mem
->size
);
80 drmUnmap(mem
->map
, mem
->size
);
81 memf
.flags
= mem
->type
;
82 memf
.offset
= mem
->offset
;
83 drmCommandWrite(nmesa
->driFd
, DRM_NOUVEAU_MEM_FREE
, &memf
, sizeof(memf
));
88 nouveau_mem_alloc(GLcontext
*ctx
, int type
, GLuint size
, GLuint align
)
90 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
91 struct drm_nouveau_mem_alloc mema
;
95 if (NOUVEAU_DEBUG
& DEBUG_MEM
) {
96 fprintf(stderr
, "%s: requested: type=0x%x, size=0x%x, align=0x%x\n",
97 __func__
, type
, (GLuint
)size
, align
);
100 mem
= CALLOC(sizeof(nouveau_mem
));
105 mema
.size
= mem
->size
= size
;
106 mema
.alignment
= align
;
108 ret
= drmCommandWriteRead(nmesa
->driFd
, DRM_NOUVEAU_MEM_ALLOC
,
109 &mema
, sizeof(mema
));
114 mem
->offset
= mema
.offset
;
115 mem
->type
= mema
.flags
;
117 if (NOUVEAU_DEBUG
& DEBUG_MEM
) {
118 fprintf(stderr
, "%s: actual: type=0x%x, offset=0x%x, size=0x%x\n",
119 __func__
, mem
->type
, (GLuint
)mem
->offset
, (GLuint
)mem
->size
);
122 if (type
& NOUVEAU_MEM_MAPPED
)
123 ret
= drmMap(nmesa
->driFd
, mema
.map_handle
, mem
->size
, &mem
->map
);
126 nouveau_mem_free(ctx
, mem
);
134 nouveau_mem_gpu_offset_get(GLcontext
*ctx
, nouveau_mem
*mem
)
136 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
142 nouveau_renderbuffer_pixelformat(nouveau_renderbuffer
*nrb
,
143 GLenum internalFormat
)
145 nrb
->mesa
.InternalFormat
= internalFormat
;
147 /*TODO: We probably want to extend this a bit, and maybe make
150 switch (internalFormat
) {
153 nrb
->mesa
._BaseFormat
= GL_RGBA
;
154 nrb
->mesa
._ActualFormat
= GL_RGBA8
;
155 nrb
->mesa
.DataType
= GL_UNSIGNED_BYTE
;
156 nrb
->mesa
.RedBits
= 8;
157 nrb
->mesa
.GreenBits
= 8;
158 nrb
->mesa
.BlueBits
= 8;
159 nrb
->mesa
.AlphaBits
= 8;
164 nrb
->mesa
._BaseFormat
= GL_RGB
;
165 nrb
->mesa
._ActualFormat
= GL_RGB5
;
166 nrb
->mesa
.DataType
= GL_UNSIGNED_BYTE
;
167 nrb
->mesa
.RedBits
= 5;
168 nrb
->mesa
.GreenBits
= 6;
169 nrb
->mesa
.BlueBits
= 5;
170 nrb
->mesa
.AlphaBits
= 0;
173 case GL_DEPTH_COMPONENT16
:
174 nrb
->mesa
._BaseFormat
= GL_DEPTH_COMPONENT
;
175 nrb
->mesa
._ActualFormat
= GL_DEPTH_COMPONENT16
;
176 nrb
->mesa
.DataType
= GL_UNSIGNED_SHORT
;
177 nrb
->mesa
.DepthBits
= 16;
180 case GL_DEPTH_COMPONENT24
:
181 nrb
->mesa
._BaseFormat
= GL_DEPTH_COMPONENT
;
182 nrb
->mesa
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
183 nrb
->mesa
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
184 nrb
->mesa
.DepthBits
= 24;
187 case GL_STENCIL_INDEX8_EXT
:
188 nrb
->mesa
._BaseFormat
= GL_STENCIL_INDEX
;
189 nrb
->mesa
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
190 nrb
->mesa
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
191 nrb
->mesa
.StencilBits
= 8;
194 case GL_DEPTH24_STENCIL8_EXT
:
195 nrb
->mesa
._BaseFormat
= GL_DEPTH_STENCIL_EXT
;
196 nrb
->mesa
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
197 nrb
->mesa
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
198 nrb
->mesa
.DepthBits
= 24;
199 nrb
->mesa
.StencilBits
= 8;
211 nouveau_renderbuffer_storage(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
212 GLenum internalFormat
,
216 nouveau_renderbuffer
*nrb
= (nouveau_renderbuffer
*)rb
;
218 if (!nouveau_renderbuffer_pixelformat(nrb
, internalFormat
)) {
219 fprintf(stderr
, "%s: unknown internalFormat\n", __func__
);
223 /* If this buffer isn't statically alloc'd, we may need to ask the
224 * drm for more memory */
225 if (!nrb
->dPriv
&& (rb
->Width
!= width
|| rb
->Height
!= height
)) {
228 /* align pitches to 64 bytes */
229 pitch
= ((width
* nrb
->cpp
) + 63) & ~63;
232 nouveau_mem_free(ctx
, nrb
->mem
);
233 nrb
->mem
= nouveau_mem_alloc(ctx
,
234 NOUVEAU_MEM_FB
| NOUVEAU_MEM_MAPPED
,
240 /* update nouveau_renderbuffer info */
241 nrb
->offset
= nouveau_mem_gpu_offset_get(ctx
, nrb
->mem
);
247 rb
->InternalFormat
= internalFormat
;
252 nouveau_renderbuffer_delete(struct gl_renderbuffer
*rb
)
254 GET_CURRENT_CONTEXT(ctx
);
255 nouveau_renderbuffer
*nrb
= (nouveau_renderbuffer
*)rb
;
258 nouveau_mem_free(ctx
, nrb
->mem
);
262 nouveau_renderbuffer
*
263 nouveau_renderbuffer_new(GLenum internalFormat
, GLvoid
*map
,
264 GLuint offset
, GLuint pitch
,
265 __DRIdrawablePrivate
*dPriv
)
267 nouveau_renderbuffer
*nrb
;
269 nrb
= CALLOC_STRUCT(nouveau_renderbuffer_t
);
271 _mesa_init_renderbuffer(&nrb
->mesa
, 0);
273 nouveau_renderbuffer_pixelformat(nrb
, internalFormat
);
275 nrb
->mesa
.AllocStorage
= nouveau_renderbuffer_storage
;
276 nrb
->mesa
.Delete
= nouveau_renderbuffer_delete
;
279 nrb
->offset
= offset
;
288 nouveau_cliprects_drawable_set(nouveauContextPtr nmesa
,
289 nouveau_renderbuffer
*nrb
)
291 __DRIdrawablePrivate
*dPriv
= nrb
->dPriv
;
293 nmesa
->numClipRects
= dPriv
->numClipRects
;
294 nmesa
->pClipRects
= dPriv
->pClipRects
;
295 nmesa
->drawX
= dPriv
->x
;
296 nmesa
->drawY
= dPriv
->y
;
297 nmesa
->drawW
= dPriv
->w
;
298 nmesa
->drawH
= dPriv
->h
;
302 nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa
,
303 nouveau_renderbuffer
*nrb
)
305 nmesa
->numClipRects
= 1;
306 nmesa
->pClipRects
= &nmesa
->osClipRect
;
307 nmesa
->osClipRect
.x1
= 0;
308 nmesa
->osClipRect
.y1
= 0;
309 nmesa
->osClipRect
.x2
= nrb
->mesa
.Width
;
310 nmesa
->osClipRect
.y2
= nrb
->mesa
.Height
;
313 nmesa
->drawW
= nrb
->mesa
.Width
;
314 nmesa
->drawH
= nrb
->mesa
.Height
;
318 nouveau_window_moved(GLcontext
*ctx
)
320 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
321 nouveau_renderbuffer
*nrb
;
323 nrb
= (nouveau_renderbuffer
*)ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
328 nouveau_cliprects_renderbuffer_set(nmesa
, nrb
);
330 nouveau_cliprects_drawable_set(nmesa
, nrb
);
332 /* Viewport depends on window size/position, nouveauCalcViewport
333 * will take care of calling the hw-specific WindowMoved
335 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
336 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
337 /* Scissor depends on window position */
338 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
339 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
343 nouveau_build_framebuffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
345 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
346 nouveau_renderbuffer
*color
[MAX_DRAW_BUFFERS
];
347 nouveau_renderbuffer
*depth
;
349 _mesa_update_framebuffer(ctx
);
350 _mesa_update_draw_buffer_bounds(ctx
);
352 color
[0] = (nouveau_renderbuffer
*)fb
->_ColorDrawBuffers
[0][0];
353 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
)
354 depth
= (nouveau_renderbuffer
*)fb
->_DepthBuffer
->Wrapped
;
356 depth
= (nouveau_renderbuffer
*)fb
->_DepthBuffer
;
358 if (!nmesa
->hw_func
.BindBuffers(nmesa
, 1, color
, depth
))
360 nouveau_window_moved(ctx
);
366 nouveauDrawBuffer(GLcontext
*ctx
, GLenum buffer
)
368 nouveau_build_framebuffer(ctx
, ctx
->DrawBuffer
);
371 static struct gl_framebuffer
*
372 nouveauNewFramebuffer(GLcontext
*ctx
, GLuint name
)
374 return _mesa_new_framebuffer(ctx
, name
);
377 static struct gl_renderbuffer
*
378 nouveauNewRenderbuffer(GLcontext
*ctx
, GLuint name
)
380 nouveau_renderbuffer
*nrb
;
382 nrb
= CALLOC_STRUCT(nouveau_renderbuffer_t
);
384 _mesa_init_renderbuffer(&nrb
->mesa
, name
);
386 nrb
->mesa
.AllocStorage
= nouveau_renderbuffer_storage
;
387 nrb
->mesa
.Delete
= nouveau_renderbuffer_delete
;
393 nouveauBindFramebuffer(GLcontext
*ctx
, GLenum target
, struct gl_framebuffer
*fb
)
395 nouveau_build_framebuffer(ctx
, fb
);
399 nouveauFramebufferRenderbuffer(GLcontext
*ctx
,
400 struct gl_framebuffer
*fb
,
402 struct gl_renderbuffer
*rb
)
404 _mesa_framebuffer_renderbuffer(ctx
, fb
, attachment
, rb
);
405 nouveau_build_framebuffer(ctx
, fb
);
409 nouveauRenderTexture(GLcontext
*ctx
,
410 struct gl_framebuffer
*fb
,
411 struct gl_renderbuffer_attachment
*att
)
416 nouveauFinishRenderTexture(GLcontext
*ctx
,
417 struct gl_renderbuffer_attachment
*att
)
422 nouveauInitBufferFuncs(struct dd_function_table
*func
)
424 func
->DrawBuffer
= nouveauDrawBuffer
;
426 func
->NewFramebuffer
= nouveauNewFramebuffer
;
427 func
->NewRenderbuffer
= nouveauNewRenderbuffer
;
428 func
->BindFramebuffer
= nouveauBindFramebuffer
;
429 func
->FramebufferRenderbuffer
= nouveauFramebufferRenderbuffer
;
430 func
->RenderTexture
= nouveauRenderTexture
;
431 func
->FinishRenderTexture
= nouveauFinishRenderTexture
;