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
: NvDmaAGP
;
36 dst_handle
= (dst
->type
& NOUVEAU_MEM_FB
) ? NvDmaFB
: NvDmaAGP
;
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 drm_nouveau_mem_free_t 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
.region_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 drm_nouveau_mem_alloc_t 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
.region_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
, mem
->offset
, 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
);
138 if (mem
->type
& NOUVEAU_MEM_FB
)
139 return (uint32_t)mem
->offset
- nmesa
->vram_phys
;
140 else if (mem
->type
& NOUVEAU_MEM_AGP
)
141 return (uint32_t)mem
->offset
- nmesa
->agp_phys
;
147 nouveau_renderbuffer_pixelformat(nouveau_renderbuffer
*nrb
,
148 GLenum internalFormat
)
150 nrb
->mesa
.InternalFormat
= internalFormat
;
152 /*TODO: We probably want to extend this a bit, and maybe make
155 switch (internalFormat
) {
158 nrb
->mesa
._BaseFormat
= GL_RGBA
;
159 nrb
->mesa
._ActualFormat
= GL_RGBA8
;
160 nrb
->mesa
.DataType
= GL_UNSIGNED_BYTE
;
161 nrb
->mesa
.RedBits
= 8;
162 nrb
->mesa
.GreenBits
= 8;
163 nrb
->mesa
.BlueBits
= 8;
164 nrb
->mesa
.AlphaBits
= 8;
169 nrb
->mesa
._BaseFormat
= GL_RGB
;
170 nrb
->mesa
._ActualFormat
= GL_RGB5
;
171 nrb
->mesa
.DataType
= GL_UNSIGNED_BYTE
;
172 nrb
->mesa
.RedBits
= 5;
173 nrb
->mesa
.GreenBits
= 6;
174 nrb
->mesa
.BlueBits
= 5;
175 nrb
->mesa
.AlphaBits
= 0;
178 case GL_DEPTH_COMPONENT16
:
179 nrb
->mesa
._BaseFormat
= GL_DEPTH_COMPONENT
;
180 nrb
->mesa
._ActualFormat
= GL_DEPTH_COMPONENT16
;
181 nrb
->mesa
.DataType
= GL_UNSIGNED_SHORT
;
182 nrb
->mesa
.DepthBits
= 16;
185 case GL_DEPTH_COMPONENT24
:
186 nrb
->mesa
._BaseFormat
= GL_DEPTH_COMPONENT
;
187 nrb
->mesa
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
188 nrb
->mesa
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
189 nrb
->mesa
.DepthBits
= 24;
192 case GL_STENCIL_INDEX8_EXT
:
193 nrb
->mesa
._BaseFormat
= GL_STENCIL_INDEX
;
194 nrb
->mesa
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
195 nrb
->mesa
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
196 nrb
->mesa
.StencilBits
= 8;
199 case GL_DEPTH24_STENCIL8_EXT
:
200 nrb
->mesa
._BaseFormat
= GL_DEPTH_STENCIL_EXT
;
201 nrb
->mesa
._ActualFormat
= GL_DEPTH24_STENCIL8_EXT
;
202 nrb
->mesa
.DataType
= GL_UNSIGNED_INT_24_8_EXT
;
203 nrb
->mesa
.DepthBits
= 24;
204 nrb
->mesa
.StencilBits
= 8;
216 nouveau_renderbuffer_storage(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
217 GLenum internalFormat
,
221 nouveau_renderbuffer
*nrb
= (nouveau_renderbuffer
*)rb
;
223 if (!nouveau_renderbuffer_pixelformat(nrb
, internalFormat
)) {
224 fprintf(stderr
, "%s: unknown internalFormat\n", __func__
);
228 /* If this buffer isn't statically alloc'd, we may need to ask the
229 * drm for more memory */
230 if (!nrb
->dPriv
&& (rb
->Width
!= width
|| rb
->Height
!= height
)) {
233 /* align pitches to 64 bytes */
234 pitch
= ((width
* nrb
->cpp
) + 63) & ~63;
237 nouveau_mem_free(ctx
, nrb
->mem
);
238 nrb
->mem
= nouveau_mem_alloc(ctx
,
239 NOUVEAU_MEM_FB
| NOUVEAU_MEM_MAPPED
,
245 /* update nouveau_renderbuffer info */
246 nrb
->offset
= nouveau_mem_gpu_offset_get(ctx
, nrb
->mem
);
252 rb
->InternalFormat
= internalFormat
;
257 nouveau_renderbuffer_delete(struct gl_renderbuffer
*rb
)
259 GET_CURRENT_CONTEXT(ctx
);
260 nouveau_renderbuffer
*nrb
= (nouveau_renderbuffer
*)rb
;
263 nouveau_mem_free(ctx
, nrb
->mem
);
267 nouveau_renderbuffer
*
268 nouveau_renderbuffer_new(GLenum internalFormat
, GLvoid
*map
,
269 GLuint offset
, GLuint pitch
,
270 __DRIdrawablePrivate
*dPriv
)
272 nouveau_renderbuffer
*nrb
;
274 nrb
= CALLOC_STRUCT(nouveau_renderbuffer_t
);
276 _mesa_init_renderbuffer(&nrb
->mesa
, 0);
278 nouveau_renderbuffer_pixelformat(nrb
, internalFormat
);
280 nrb
->mesa
.AllocStorage
= nouveau_renderbuffer_storage
;
281 nrb
->mesa
.Delete
= nouveau_renderbuffer_delete
;
284 nrb
->offset
= offset
;
293 nouveau_cliprects_drawable_set(nouveauContextPtr nmesa
,
294 nouveau_renderbuffer
*nrb
)
296 __DRIdrawablePrivate
*dPriv
= nrb
->dPriv
;
298 nmesa
->numClipRects
= dPriv
->numClipRects
;
299 nmesa
->pClipRects
= dPriv
->pClipRects
;
300 nmesa
->drawX
= dPriv
->x
;
301 nmesa
->drawY
= dPriv
->y
;
305 nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa
,
306 nouveau_renderbuffer
*nrb
)
308 nmesa
->numClipRects
= 1;
309 nmesa
->pClipRects
= &nmesa
->osClipRect
;
310 nmesa
->osClipRect
.x1
= 0;
311 nmesa
->osClipRect
.y1
= 0;
312 nmesa
->osClipRect
.x2
= nrb
->mesa
.Width
;
313 nmesa
->osClipRect
.y2
= nrb
->mesa
.Height
;
319 nouveau_window_moved(GLcontext
*ctx
)
321 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
322 nouveau_renderbuffer
*nrb
;
324 nrb
= (nouveau_renderbuffer
*)ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
329 nouveau_cliprects_renderbuffer_set(nmesa
, nrb
);
331 nouveau_cliprects_drawable_set(nmesa
, nrb
);
333 /* Viewport depends on window size/position, nouveauCalcViewport
334 * will take care of calling the hw-specific WindowMoved
336 ctx
->Driver
.Viewport(ctx
, ctx
->Viewport
.X
, ctx
->Viewport
.Y
,
337 ctx
->Viewport
.Width
, ctx
->Viewport
.Height
);
338 /* Scissor depends on window position */
339 ctx
->Driver
.Scissor(ctx
, ctx
->Scissor
.X
, ctx
->Scissor
.Y
,
340 ctx
->Scissor
.Width
, ctx
->Scissor
.Height
);
344 nouveau_build_framebuffer(GLcontext
*ctx
, struct gl_framebuffer
*fb
)
346 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
347 nouveau_renderbuffer
*color
[MAX_DRAW_BUFFERS
];
348 nouveau_renderbuffer
*depth
;
350 _mesa_update_framebuffer(ctx
);
351 _mesa_update_draw_buffer_bounds(ctx
);
353 color
[0] = (nouveau_renderbuffer
*)fb
->_ColorDrawBuffers
[0][0];
354 if (fb
->_DepthBuffer
&& fb
->_DepthBuffer
->Wrapped
)
355 depth
= (nouveau_renderbuffer
*)fb
->_DepthBuffer
->Wrapped
;
357 depth
= (nouveau_renderbuffer
*)fb
->_DepthBuffer
;
359 if (!nmesa
->hw_func
.BindBuffers(nmesa
, 1, color
, depth
))
361 nouveau_window_moved(ctx
);
367 nouveauDrawBuffer(GLcontext
*ctx
, GLenum buffer
)
369 nouveau_build_framebuffer(ctx
, ctx
->DrawBuffer
);
372 static struct gl_framebuffer
*
373 nouveauNewFramebuffer(GLcontext
*ctx
, GLuint name
)
375 return _mesa_new_framebuffer(ctx
, name
);
378 static struct gl_renderbuffer
*
379 nouveauNewRenderbuffer(GLcontext
*ctx
, GLuint name
)
381 nouveau_renderbuffer
*nrb
;
383 nrb
= CALLOC_STRUCT(nouveau_renderbuffer_t
);
385 _mesa_init_renderbuffer(&nrb
->mesa
, name
);
387 nrb
->mesa
.AllocStorage
= nouveau_renderbuffer_storage
;
388 nrb
->mesa
.Delete
= nouveau_renderbuffer_delete
;
394 nouveauBindFramebuffer(GLcontext
*ctx
, GLenum target
, struct gl_framebuffer
*fb
)
396 nouveau_build_framebuffer(ctx
, fb
);
400 nouveauFramebufferRenderbuffer(GLcontext
*ctx
,
401 struct gl_framebuffer
*fb
,
403 struct gl_renderbuffer
*rb
)
405 _mesa_framebuffer_renderbuffer(ctx
, fb
, attachment
, rb
);
406 nouveau_build_framebuffer(ctx
, fb
);
410 nouveauRenderTexture(GLcontext
*ctx
,
411 struct gl_framebuffer
*fb
,
412 struct gl_renderbuffer_attachment
*att
)
417 nouveauFinishRenderTexture(GLcontext
*ctx
,
418 struct gl_renderbuffer_attachment
*att
)
423 nouveauInitBufferFuncs(struct dd_function_table
*func
)
425 func
->DrawBuffer
= nouveauDrawBuffer
;
427 func
->NewFramebuffer
= nouveauNewFramebuffer
;
428 func
->NewRenderbuffer
= nouveauNewRenderbuffer
;
429 func
->BindFramebuffer
= nouveauBindFramebuffer
;
430 func
->FramebufferRenderbuffer
= nouveauFramebufferRenderbuffer
;
431 func
->RenderTexture
= nouveauRenderTexture
;
432 func
->FinishRenderTexture
= nouveauFinishRenderTexture
;