From: Ben Skeggs Date: Mon, 13 Aug 2007 10:02:04 +0000 (+1000) Subject: nouveau: Split nouveau_buffers into nouveau_mem and nouveau_fbo X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b7c93de6d798d7ccfc7bfa12b9c8f474de955d55;p=mesa.git nouveau: Split nouveau_buffers into nouveau_mem and nouveau_fbo --- diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile index 20d2de5eefb..6ea4594f1e6 100644 --- a/src/mesa/drivers/dri/nouveau/Makefile +++ b/src/mesa/drivers/dri/nouveau/Makefile @@ -9,12 +9,13 @@ MINIGLX_SOURCES = DRIVER_SOURCES = \ nouveau_bufferobj.c \ - nouveau_buffers.c \ nouveau_card.c \ nouveau_context.c \ nouveau_driver.c \ + nouveau_fbo.c \ nouveau_fifo.c \ nouveau_lock.c \ + nouveau_mem.c \ nouveau_object.c \ nouveau_screen.c \ nouveau_span.c \ diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c index fc14060c049..be6455a01ed 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c @@ -2,11 +2,11 @@ #include "enums.h" #include "nouveau_bufferobj.h" -#include "nouveau_buffers.h" #include "nouveau_context.h" #include "nouveau_drm.h" -#include "nouveau_object.h" +#include "nouveau_mem.h" #include "nouveau_msg.h" +#include "nouveau_object.h" #define NOUVEAU_MEM_FREE(mem) do { \ nouveau_mem_free(ctx, (mem)); \ diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h index 3439a35e7c8..cbc89a151da 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h @@ -2,7 +2,7 @@ #define __NOUVEAU_BUFFEROBJ_H__ #include "mtypes.h" -#include "nouveau_buffers.h" +#include "nouveau_mem.h" #define NOUVEAU_BO_VRAM_OK (NOUVEAU_MEM_FB | NOUVEAU_MEM_FB_ACCEPTABLE) #define NOUVEAU_BO_GART_OK (NOUVEAU_MEM_AGP | NOUVEAU_MEM_AGP_ACCEPTABLE) diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c deleted file mode 100644 index 7cf739fe47b..00000000000 --- a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c +++ /dev/null @@ -1,440 +0,0 @@ -#include "utils.h" -#include "framebuffer.h" -#include "renderbuffer.h" -#include "fbobject.h" - -#include "nouveau_context.h" -#include "nouveau_buffers.h" -#include "nouveau_object.h" -#include "nouveau_fifo.h" -#include "nouveau_reg.h" -#include "nouveau_msg.h" - -#define MAX_MEMFMT_LENGTH 32768 - -/* Unstrided blit using NV_MEMORY_TO_MEMORY_FORMAT */ -GLboolean -nouveau_memformat_flat_emit(GLcontext * ctx, - nouveau_mem * dst, nouveau_mem * src, - GLuint dst_offset, GLuint src_offset, - GLuint size) -{ - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - uint32_t src_handle, dst_handle; - GLuint count; - - if (src_offset + size > src->size) { - MESSAGE("src out of nouveau_mem bounds\n"); - return GL_FALSE; - } - if (dst_offset + size > dst->size) { - MESSAGE("dst out of nouveau_mem bounds\n"); - return GL_FALSE; - } - - src_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT; - dst_handle = (dst->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT; - src_offset += nouveau_mem_gpu_offset_get(ctx, src); - dst_offset += nouveau_mem_gpu_offset_get(ctx, dst); - - BEGIN_RING_SIZE(NvSubMemFormat, - NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN, 2); - OUT_RING(src_handle); - OUT_RING(dst_handle); - - count = (size / MAX_MEMFMT_LENGTH) + - ((size % MAX_MEMFMT_LENGTH) ? 1 : 0); - - while (count--) { - GLuint length = - (size > MAX_MEMFMT_LENGTH) ? MAX_MEMFMT_LENGTH : size; - - BEGIN_RING_SIZE(NvSubMemFormat, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - OUT_RING(src_offset); - OUT_RING(dst_offset); - OUT_RING(0); /* pitch in */ - OUT_RING(0); /* pitch out */ - OUT_RING(length); /* line length */ - OUT_RING(1); /* number of lines */ - OUT_RING((1 << 8) /* dst_inc */ |(1 << 0) /* src_inc */ ); - OUT_RING(0); /* buffer notify? */ - FIRE_RING(); - - src_offset += length; - dst_offset += length; - size -= length; - } - - return GL_TRUE; -} - -void nouveau_mem_free(GLcontext * ctx, nouveau_mem * mem) -{ - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - struct drm_nouveau_mem_free memf; - - if (NOUVEAU_DEBUG & DEBUG_MEM) { - fprintf(stderr, "%s: type=0x%x, offset=0x%x, size=0x%x\n", - __func__, mem->type, (GLuint) mem->offset, - (GLuint) mem->size); - } - - if (mem->map) - drmUnmap(mem->map, mem->size); - memf.flags = mem->type; - memf.offset = mem->offset; - drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_MEM_FREE, &memf, - sizeof(memf)); - FREE(mem); -} - -nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, uint32_t flags, GLuint size, - GLuint align) -{ - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - struct drm_nouveau_mem_alloc mema; - nouveau_mem *mem; - int ret; - - if (NOUVEAU_DEBUG & DEBUG_MEM) { - fprintf(stderr, - "%s: requested: flags=0x%x, size=0x%x, align=0x%x\n", - __func__, flags, (GLuint) size, align); - } - - mem = CALLOC(sizeof(nouveau_mem)); - if (!mem) - return NULL; - - mema.flags = flags; - mema.size = mem->size = size; - mema.alignment = align; - mem->map = NULL; - ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC, - &mema, sizeof(mema)); - if (ret) { - FREE(mem); - return NULL; - } - mem->offset = mema.offset; - mem->type = mema.flags; - - if (NOUVEAU_DEBUG & DEBUG_MEM) { - fprintf(stderr, - "%s: actual: type=0x%x, offset=0x%x, size=0x%x\n", - __func__, mem->type, (GLuint) mem->offset, - (GLuint) mem->size); - } - - if (flags & NOUVEAU_MEM_MAPPED) - ret = drmMap(nmesa->driFd, mema.map_handle, mem->size, - &mem->map); - if (ret) { - mem->map = NULL; - nouveau_mem_free(ctx, mem); - mem = NULL; - } - - return mem; -} - -uint32_t nouveau_mem_gpu_offset_get(GLcontext * ctx, nouveau_mem * mem) -{ - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - - return mem->offset; -} - -static GLboolean -nouveau_renderbuffer_pixelformat(nouveau_renderbuffer * nrb, - GLenum internalFormat) -{ - nrb->mesa.InternalFormat = internalFormat; - - /*TODO: We probably want to extend this a bit, and maybe make - * card-specific? - */ - switch (internalFormat) { - case GL_RGBA: - case GL_RGBA8: - nrb->mesa._BaseFormat = GL_RGBA; - nrb->mesa._ActualFormat = GL_RGBA8; - nrb->mesa.DataType = GL_UNSIGNED_BYTE; - nrb->mesa.RedBits = 8; - nrb->mesa.GreenBits = 8; - nrb->mesa.BlueBits = 8; - nrb->mesa.AlphaBits = 8; - nrb->cpp = 4; - break; - case GL_RGB: - case GL_RGB5: - nrb->mesa._BaseFormat = GL_RGB; - nrb->mesa._ActualFormat = GL_RGB5; - nrb->mesa.DataType = GL_UNSIGNED_BYTE; - nrb->mesa.RedBits = 5; - nrb->mesa.GreenBits = 6; - nrb->mesa.BlueBits = 5; - nrb->mesa.AlphaBits = 0; - nrb->cpp = 2; - break; - case GL_DEPTH_COMPONENT16: - nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT; - nrb->mesa._ActualFormat = GL_DEPTH_COMPONENT16; - nrb->mesa.DataType = GL_UNSIGNED_SHORT; - nrb->mesa.DepthBits = 16; - nrb->cpp = 2; - break; - case GL_DEPTH_COMPONENT24: - nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT; - nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT; - nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT; - nrb->mesa.DepthBits = 24; - nrb->cpp = 4; - break; - case GL_STENCIL_INDEX8_EXT: - nrb->mesa._BaseFormat = GL_STENCIL_INDEX; - nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT; - nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT; - nrb->mesa.StencilBits = 8; - nrb->cpp = 4; - break; - case GL_DEPTH24_STENCIL8_EXT: - nrb->mesa._BaseFormat = GL_DEPTH_STENCIL_EXT; - nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT; - nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT; - nrb->mesa.DepthBits = 24; - nrb->mesa.StencilBits = 8; - nrb->cpp = 4; - break; - default: - return GL_FALSE; - break; - } - - return GL_TRUE; -} - -static GLboolean -nouveau_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, - GLenum internalFormat, - GLuint width, GLuint height) -{ - nouveau_renderbuffer *nrb = (nouveau_renderbuffer *) rb; - - if (!nouveau_renderbuffer_pixelformat(nrb, internalFormat)) { - fprintf(stderr, "%s: unknown internalFormat\n", __func__); - return GL_FALSE; - } - - /* If this buffer isn't statically alloc'd, we may need to ask the - * drm for more memory */ - if (!nrb->dPriv && (rb->Width != width || rb->Height != height)) { - GLuint pitch; - - /* align pitches to 64 bytes */ - pitch = ((width * nrb->cpp) + 63) & ~63; - - if (nrb->mem) - nouveau_mem_free(ctx, nrb->mem); - nrb->mem = nouveau_mem_alloc(ctx, - NOUVEAU_MEM_FB | - NOUVEAU_MEM_MAPPED, - pitch * height, 0); - if (!nrb->mem) - return GL_FALSE; - - /* update nouveau_renderbuffer info */ - nrb->offset = nouveau_mem_gpu_offset_get(ctx, nrb->mem); - nrb->pitch = pitch; - } - - rb->Width = width; - rb->Height = height; - rb->InternalFormat = internalFormat; - return GL_TRUE; -} - -static void nouveau_renderbuffer_delete(struct gl_renderbuffer *rb) -{ - GET_CURRENT_CONTEXT(ctx); - nouveau_renderbuffer *nrb = (nouveau_renderbuffer *) rb; - - if (nrb->mem) - nouveau_mem_free(ctx, nrb->mem); - FREE(nrb); -} - -nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat, - GLvoid * map, GLuint offset, - GLuint pitch, - __DRIdrawablePrivate * - dPriv) -{ - nouveau_renderbuffer *nrb; - - nrb = CALLOC_STRUCT(nouveau_renderbuffer_t); - if (nrb) { - _mesa_init_renderbuffer(&nrb->mesa, 0); - - nouveau_renderbuffer_pixelformat(nrb, internalFormat); - - nrb->mesa.AllocStorage = nouveau_renderbuffer_storage; - nrb->mesa.Delete = nouveau_renderbuffer_delete; - - nrb->dPriv = dPriv; - nrb->offset = offset; - nrb->pitch = pitch; - nrb->map = map; - } - - return nrb; -} - -static void -nouveau_cliprects_drawable_set(nouveauContextPtr nmesa, - nouveau_renderbuffer * nrb) -{ - __DRIdrawablePrivate *dPriv = nrb->dPriv; - - nmesa->numClipRects = dPriv->numClipRects; - nmesa->pClipRects = dPriv->pClipRects; - nmesa->drawX = dPriv->x; - nmesa->drawY = dPriv->y; - nmesa->drawW = dPriv->w; - nmesa->drawH = dPriv->h; -} - -static void -nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa, - nouveau_renderbuffer * nrb) -{ - nmesa->numClipRects = 1; - nmesa->pClipRects = &nmesa->osClipRect; - nmesa->osClipRect.x1 = 0; - nmesa->osClipRect.y1 = 0; - nmesa->osClipRect.x2 = nrb->mesa.Width; - nmesa->osClipRect.y2 = nrb->mesa.Height; - nmesa->drawX = 0; - nmesa->drawY = 0; - nmesa->drawW = nrb->mesa.Width; - nmesa->drawH = nrb->mesa.Height; -} - -void nouveau_window_moved(GLcontext * ctx) -{ - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - nouveau_renderbuffer *nrb; - - nrb = (nouveau_renderbuffer *)ctx->DrawBuffer->_ColorDrawBuffers[0][0]; - if (!nrb) - return; - - if (!nrb->dPriv) - nouveau_cliprects_renderbuffer_set(nmesa, nrb); - else - nouveau_cliprects_drawable_set(nmesa, nrb); - - /* Viewport depends on window size/position, nouveauCalcViewport - * will take care of calling the hw-specific WindowMoved - */ - ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y, - ctx->Viewport.Width, ctx->Viewport.Height); - /* Scissor depends on window position */ - ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, - ctx->Scissor.Width, ctx->Scissor.Height); -} - -GLboolean -nouveau_build_framebuffer(GLcontext * ctx, struct gl_framebuffer *fb) -{ - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - nouveau_renderbuffer *color[MAX_DRAW_BUFFERS]; - nouveau_renderbuffer *depth; - - _mesa_update_framebuffer(ctx); - _mesa_update_draw_buffer_bounds(ctx); - - color[0] = (nouveau_renderbuffer *) fb->_ColorDrawBuffers[0][0]; - if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) - depth = (nouveau_renderbuffer *) fb->_DepthBuffer->Wrapped; - else - depth = (nouveau_renderbuffer *) fb->_DepthBuffer; - - if (!nmesa->hw_func.BindBuffers(nmesa, 1, color, depth)) - return GL_FALSE; - nouveau_window_moved(ctx); - - return GL_TRUE; -} - -static void nouveauDrawBuffer(GLcontext * ctx, GLenum buffer) -{ - nouveau_build_framebuffer(ctx, ctx->DrawBuffer); -} - -static struct gl_framebuffer *nouveauNewFramebuffer(GLcontext * ctx, - GLuint name) -{ - return _mesa_new_framebuffer(ctx, name); -} - -static struct gl_renderbuffer *nouveauNewRenderbuffer(GLcontext * ctx, - GLuint name) -{ - nouveau_renderbuffer *nrb; - - nrb = CALLOC_STRUCT(nouveau_renderbuffer_t); - if (nrb) { - _mesa_init_renderbuffer(&nrb->mesa, name); - - nrb->mesa.AllocStorage = nouveau_renderbuffer_storage; - nrb->mesa.Delete = nouveau_renderbuffer_delete; - } - return &nrb->mesa; -} - -static void -nouveauBindFramebuffer(GLcontext * ctx, GLenum target, - struct gl_framebuffer *fb, - struct gl_framebuffer *fbread) -{ - if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { - nouveau_build_framebuffer(ctx, fb); - } -} - -static void -nouveauFramebufferRenderbuffer(GLcontext * ctx, - struct gl_framebuffer *fb, - GLenum attachment, - struct gl_renderbuffer *rb) -{ - _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); - nouveau_build_framebuffer(ctx, fb); -} - -static void -nouveauRenderTexture(GLcontext * ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att) -{ -} - -static void -nouveauFinishRenderTexture(GLcontext * ctx, - struct gl_renderbuffer_attachment *att) -{ -} - -void nouveauInitBufferFuncs(struct dd_function_table *func) -{ - func->DrawBuffer = nouveauDrawBuffer; - - func->NewFramebuffer = nouveauNewFramebuffer; - func->NewRenderbuffer = nouveauNewRenderbuffer; - func->BindFramebuffer = nouveauBindFramebuffer; - func->FramebufferRenderbuffer = nouveauFramebufferRenderbuffer; - func->RenderTexture = nouveauRenderTexture; - func->FinishRenderTexture = nouveauFinishRenderTexture; -} diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.h b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h deleted file mode 100644 index f0987d2aa7d..00000000000 --- a/src/mesa/drivers/dri/nouveau/nouveau_buffers.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __NOUVEAU_BUFFERS_H__ -#define __NOUVEAU_BUFFERS_H__ - -#include -#include "mtypes.h" -#include "utils.h" -#include "renderbuffer.h" - -typedef struct nouveau_mem_t { - int type; - uint64_t offset; - uint64_t size; - void *map; -} nouveau_mem; - -extern nouveau_mem *nouveau_mem_alloc(GLcontext *, uint32_t flags, - GLuint size, GLuint align); -extern void nouveau_mem_free(GLcontext *, nouveau_mem *); -extern uint32_t nouveau_mem_gpu_offset_get(GLcontext *, nouveau_mem *); - -extern GLboolean nouveau_memformat_flat_emit(GLcontext *, - nouveau_mem *dst, - nouveau_mem *src, - GLuint dst_offset, - GLuint src_offset, - GLuint size); - -typedef struct nouveau_renderbuffer_t { - struct gl_renderbuffer mesa; /* must be first! */ - __DRIdrawablePrivate *dPriv; - - nouveau_mem *mem; - void *map; - - int cpp; - uint32_t offset; - uint32_t pitch; -} nouveau_renderbuffer; - -extern nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat, - GLvoid *map, - GLuint offset, - GLuint pitch, - __DRIdrawablePrivate *); -extern void nouveau_window_moved(GLcontext *); -extern GLboolean nouveau_build_framebuffer(GLcontext *, - struct gl_framebuffer *); -extern nouveau_renderbuffer *nouveau_current_draw_buffer(GLcontext *); - -extern void nouveauInitBufferFuncs(struct dd_function_table *); - -#endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h index fdbde51a728..03f778a13c4 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h @@ -36,10 +36,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "mtypes.h" #include "tnl/t_vertex.h" +#include "nouveau_fbo.h" #include "nouveau_screen.h" -#include "nouveau_state_cache.h" -#include "nouveau_buffers.h" #include "nouveau_shader.h" +#include "nouveau_state_cache.h" #include "nouveau_sync.h" #include "xmlconfig.h" diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fbo.c b/src/mesa/drivers/dri/nouveau/nouveau_fbo.c new file mode 100644 index 00000000000..54c0c26d083 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_fbo.c @@ -0,0 +1,304 @@ +#include "utils.h" +#include "framebuffer.h" +#include "renderbuffer.h" +#include "fbobject.h" + +#include "nouveau_context.h" +#include "nouveau_fbo.h" +#include "nouveau_fifo.h" +#include "nouveau_msg.h" +#include "nouveau_object.h" +#include "nouveau_reg.h" + +static GLboolean +nouveau_renderbuffer_pixelformat(nouveau_renderbuffer * nrb, + GLenum internalFormat) +{ + nrb->mesa.InternalFormat = internalFormat; + + /*TODO: We probably want to extend this a bit, and maybe make + * card-specific? + */ + switch (internalFormat) { + case GL_RGBA: + case GL_RGBA8: + nrb->mesa._BaseFormat = GL_RGBA; + nrb->mesa._ActualFormat = GL_RGBA8; + nrb->mesa.DataType = GL_UNSIGNED_BYTE; + nrb->mesa.RedBits = 8; + nrb->mesa.GreenBits = 8; + nrb->mesa.BlueBits = 8; + nrb->mesa.AlphaBits = 8; + nrb->cpp = 4; + break; + case GL_RGB: + case GL_RGB5: + nrb->mesa._BaseFormat = GL_RGB; + nrb->mesa._ActualFormat = GL_RGB5; + nrb->mesa.DataType = GL_UNSIGNED_BYTE; + nrb->mesa.RedBits = 5; + nrb->mesa.GreenBits = 6; + nrb->mesa.BlueBits = 5; + nrb->mesa.AlphaBits = 0; + nrb->cpp = 2; + break; + case GL_DEPTH_COMPONENT16: + nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT; + nrb->mesa._ActualFormat = GL_DEPTH_COMPONENT16; + nrb->mesa.DataType = GL_UNSIGNED_SHORT; + nrb->mesa.DepthBits = 16; + nrb->cpp = 2; + break; + case GL_DEPTH_COMPONENT24: + nrb->mesa._BaseFormat = GL_DEPTH_COMPONENT; + nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT; + nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT; + nrb->mesa.DepthBits = 24; + nrb->cpp = 4; + break; + case GL_STENCIL_INDEX8_EXT: + nrb->mesa._BaseFormat = GL_STENCIL_INDEX; + nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT; + nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT; + nrb->mesa.StencilBits = 8; + nrb->cpp = 4; + break; + case GL_DEPTH24_STENCIL8_EXT: + nrb->mesa._BaseFormat = GL_DEPTH_STENCIL_EXT; + nrb->mesa._ActualFormat = GL_DEPTH24_STENCIL8_EXT; + nrb->mesa.DataType = GL_UNSIGNED_INT_24_8_EXT; + nrb->mesa.DepthBits = 24; + nrb->mesa.StencilBits = 8; + nrb->cpp = 4; + break; + default: + return GL_FALSE; + break; + } + + return GL_TRUE; +} + +static GLboolean +nouveau_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, GLuint height) +{ + nouveau_renderbuffer *nrb = (nouveau_renderbuffer *) rb; + + if (!nouveau_renderbuffer_pixelformat(nrb, internalFormat)) { + fprintf(stderr, "%s: unknown internalFormat\n", __func__); + return GL_FALSE; + } + + /* If this buffer isn't statically alloc'd, we may need to ask the + * drm for more memory */ + if (!nrb->dPriv && (rb->Width != width || rb->Height != height)) { + GLuint pitch; + + /* align pitches to 64 bytes */ + pitch = ((width * nrb->cpp) + 63) & ~63; + + if (nrb->mem) + nouveau_mem_free(ctx, nrb->mem); + nrb->mem = nouveau_mem_alloc(ctx, + NOUVEAU_MEM_FB | + NOUVEAU_MEM_MAPPED, + pitch * height, 0); + if (!nrb->mem) + return GL_FALSE; + + /* update nouveau_renderbuffer info */ + nrb->offset = nouveau_mem_gpu_offset_get(ctx, nrb->mem); + nrb->pitch = pitch; + } + + rb->Width = width; + rb->Height = height; + rb->InternalFormat = internalFormat; + return GL_TRUE; +} + +static void nouveau_renderbuffer_delete(struct gl_renderbuffer *rb) +{ + GET_CURRENT_CONTEXT(ctx); + nouveau_renderbuffer *nrb = (nouveau_renderbuffer *) rb; + + if (nrb->mem) + nouveau_mem_free(ctx, nrb->mem); + FREE(nrb); +} + +nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat, + GLvoid * map, GLuint offset, + GLuint pitch, + __DRIdrawablePrivate * + dPriv) +{ + nouveau_renderbuffer *nrb; + + nrb = CALLOC_STRUCT(nouveau_renderbuffer_t); + if (nrb) { + _mesa_init_renderbuffer(&nrb->mesa, 0); + + nouveau_renderbuffer_pixelformat(nrb, internalFormat); + + nrb->mesa.AllocStorage = nouveau_renderbuffer_storage; + nrb->mesa.Delete = nouveau_renderbuffer_delete; + + nrb->dPriv = dPriv; + nrb->offset = offset; + nrb->pitch = pitch; + nrb->map = map; + } + + return nrb; +} + +static void +nouveau_cliprects_drawable_set(nouveauContextPtr nmesa, + nouveau_renderbuffer * nrb) +{ + __DRIdrawablePrivate *dPriv = nrb->dPriv; + + nmesa->numClipRects = dPriv->numClipRects; + nmesa->pClipRects = dPriv->pClipRects; + nmesa->drawX = dPriv->x; + nmesa->drawY = dPriv->y; + nmesa->drawW = dPriv->w; + nmesa->drawH = dPriv->h; +} + +static void +nouveau_cliprects_renderbuffer_set(nouveauContextPtr nmesa, + nouveau_renderbuffer * nrb) +{ + nmesa->numClipRects = 1; + nmesa->pClipRects = &nmesa->osClipRect; + nmesa->osClipRect.x1 = 0; + nmesa->osClipRect.y1 = 0; + nmesa->osClipRect.x2 = nrb->mesa.Width; + nmesa->osClipRect.y2 = nrb->mesa.Height; + nmesa->drawX = 0; + nmesa->drawY = 0; + nmesa->drawW = nrb->mesa.Width; + nmesa->drawH = nrb->mesa.Height; +} + +void nouveau_window_moved(GLcontext * ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_renderbuffer *nrb; + + nrb = (nouveau_renderbuffer *)ctx->DrawBuffer->_ColorDrawBuffers[0][0]; + if (!nrb) + return; + + if (!nrb->dPriv) + nouveau_cliprects_renderbuffer_set(nmesa, nrb); + else + nouveau_cliprects_drawable_set(nmesa, nrb); + + /* Viewport depends on window size/position, nouveauCalcViewport + * will take care of calling the hw-specific WindowMoved + */ + ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y, + ctx->Viewport.Width, ctx->Viewport.Height); + /* Scissor depends on window position */ + ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, + ctx->Scissor.Width, ctx->Scissor.Height); +} + +GLboolean +nouveau_build_framebuffer(GLcontext * ctx, struct gl_framebuffer *fb) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_renderbuffer *color[MAX_DRAW_BUFFERS]; + nouveau_renderbuffer *depth; + + _mesa_update_framebuffer(ctx); + _mesa_update_draw_buffer_bounds(ctx); + + color[0] = (nouveau_renderbuffer *) fb->_ColorDrawBuffers[0][0]; + if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) + depth = (nouveau_renderbuffer *) fb->_DepthBuffer->Wrapped; + else + depth = (nouveau_renderbuffer *) fb->_DepthBuffer; + + if (!nmesa->hw_func.BindBuffers(nmesa, 1, color, depth)) + return GL_FALSE; + nouveau_window_moved(ctx); + + return GL_TRUE; +} + +static void nouveauDrawBuffer(GLcontext * ctx, GLenum buffer) +{ + nouveau_build_framebuffer(ctx, ctx->DrawBuffer); +} + +static struct gl_framebuffer *nouveauNewFramebuffer(GLcontext * ctx, + GLuint name) +{ + return _mesa_new_framebuffer(ctx, name); +} + +static struct gl_renderbuffer *nouveauNewRenderbuffer(GLcontext * ctx, + GLuint name) +{ + nouveau_renderbuffer *nrb; + + nrb = CALLOC_STRUCT(nouveau_renderbuffer_t); + if (nrb) { + _mesa_init_renderbuffer(&nrb->mesa, name); + + nrb->mesa.AllocStorage = nouveau_renderbuffer_storage; + nrb->mesa.Delete = nouveau_renderbuffer_delete; + } + return &nrb->mesa; +} + +static void +nouveauBindFramebuffer(GLcontext * ctx, GLenum target, + struct gl_framebuffer *fb, + struct gl_framebuffer *fbread) +{ + if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { + nouveau_build_framebuffer(ctx, fb); + } +} + +static void +nouveauFramebufferRenderbuffer(GLcontext * ctx, + struct gl_framebuffer *fb, + GLenum attachment, + struct gl_renderbuffer *rb) +{ + _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); + nouveau_build_framebuffer(ctx, fb); +} + +static void +nouveauRenderTexture(GLcontext * ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att) +{ +} + +static void +nouveauFinishRenderTexture(GLcontext * ctx, + struct gl_renderbuffer_attachment *att) +{ +} + +void nouveauInitBufferFuncs(struct dd_function_table *func) +{ + func->DrawBuffer = nouveauDrawBuffer; + + func->NewFramebuffer = nouveauNewFramebuffer; + func->NewRenderbuffer = nouveauNewRenderbuffer; + func->BindFramebuffer = nouveauBindFramebuffer; + func->FramebufferRenderbuffer = nouveauFramebufferRenderbuffer; + func->RenderTexture = nouveauRenderTexture; + func->FinishRenderTexture = nouveauFinishRenderTexture; +} diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fbo.h b/src/mesa/drivers/dri/nouveau/nouveau_fbo.h new file mode 100644 index 00000000000..757a784f8f8 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_fbo.h @@ -0,0 +1,35 @@ +#ifndef __NOUVEAU_BUFFERS_H__ +#define __NOUVEAU_BUFFERS_H__ + +#include +#include "mtypes.h" +#include "utils.h" +#include "renderbuffer.h" + +#include "nouveau_mem.h" + +typedef struct nouveau_renderbuffer_t { + struct gl_renderbuffer mesa; /* must be first! */ + __DRIdrawablePrivate *dPriv; + + nouveau_mem *mem; + void *map; + + int cpp; + uint32_t offset; + uint32_t pitch; +} nouveau_renderbuffer; + +extern nouveau_renderbuffer *nouveau_renderbuffer_new(GLenum internalFormat, + GLvoid *map, + GLuint offset, + GLuint pitch, + __DRIdrawablePrivate *); +extern void nouveau_window_moved(GLcontext *); +extern GLboolean nouveau_build_framebuffer(GLcontext *, + struct gl_framebuffer *); +extern nouveau_renderbuffer *nouveau_current_draw_buffer(GLcontext *); + +extern void nouveauInitBufferFuncs(struct dd_function_table *); + +#endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_mem.c b/src/mesa/drivers/dri/nouveau/nouveau_mem.c new file mode 100644 index 00000000000..35c53268b06 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_mem.c @@ -0,0 +1,144 @@ +#include "mtypes.h" + +#include "nouveau_context.h" +#include "nouveau_fifo.h" +#include "nouveau_mem.h" +#include "nouveau_msg.h" +#include "nouveau_object.h" +#include "nouveau_reg.h" + +#define MAX_MEMFMT_LENGTH 32768 + +/* Unstrided blit using NV_MEMORY_TO_MEMORY_FORMAT */ +GLboolean +nouveau_memformat_flat_emit(GLcontext * ctx, + nouveau_mem * dst, nouveau_mem * src, + GLuint dst_offset, GLuint src_offset, + GLuint size) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + uint32_t src_handle, dst_handle; + GLuint count; + + if (src_offset + size > src->size) { + MESSAGE("src out of nouveau_mem bounds\n"); + return GL_FALSE; + } + if (dst_offset + size > dst->size) { + MESSAGE("dst out of nouveau_mem bounds\n"); + return GL_FALSE; + } + + src_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT; + dst_handle = (dst->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaTT; + src_offset += nouveau_mem_gpu_offset_get(ctx, src); + dst_offset += nouveau_mem_gpu_offset_get(ctx, dst); + + BEGIN_RING_SIZE(NvSubMemFormat, + NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN, 2); + OUT_RING(src_handle); + OUT_RING(dst_handle); + + count = (size / MAX_MEMFMT_LENGTH) + + ((size % MAX_MEMFMT_LENGTH) ? 1 : 0); + + while (count--) { + GLuint length = + (size > MAX_MEMFMT_LENGTH) ? MAX_MEMFMT_LENGTH : size; + + BEGIN_RING_SIZE(NvSubMemFormat, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + OUT_RING(src_offset); + OUT_RING(dst_offset); + OUT_RING(0); /* pitch in */ + OUT_RING(0); /* pitch out */ + OUT_RING(length); /* line length */ + OUT_RING(1); /* number of lines */ + OUT_RING((1 << 8) /* dst_inc */ |(1 << 0) /* src_inc */ ); + OUT_RING(0); /* buffer notify? */ + FIRE_RING(); + + src_offset += length; + dst_offset += length; + size -= length; + } + + return GL_TRUE; +} + +void nouveau_mem_free(GLcontext * ctx, nouveau_mem * mem) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + struct drm_nouveau_mem_free memf; + + if (NOUVEAU_DEBUG & DEBUG_MEM) { + fprintf(stderr, "%s: type=0x%x, offset=0x%x, size=0x%x\n", + __func__, mem->type, (GLuint) mem->offset, + (GLuint) mem->size); + } + + if (mem->map) + drmUnmap(mem->map, mem->size); + memf.flags = mem->type; + memf.offset = mem->offset; + drmCommandWrite(nmesa->driFd, DRM_NOUVEAU_MEM_FREE, &memf, + sizeof(memf)); + FREE(mem); +} + +nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, uint32_t flags, GLuint size, + GLuint align) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + struct drm_nouveau_mem_alloc mema; + nouveau_mem *mem; + int ret; + + if (NOUVEAU_DEBUG & DEBUG_MEM) { + fprintf(stderr, + "%s: requested: flags=0x%x, size=0x%x, align=0x%x\n", + __func__, flags, (GLuint) size, align); + } + + mem = CALLOC(sizeof(nouveau_mem)); + if (!mem) + return NULL; + + mema.flags = flags; + mema.size = mem->size = size; + mema.alignment = align; + mem->map = NULL; + ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_MEM_ALLOC, + &mema, sizeof(mema)); + if (ret) { + FREE(mem); + return NULL; + } + mem->offset = mema.offset; + mem->type = mema.flags; + + if (NOUVEAU_DEBUG & DEBUG_MEM) { + fprintf(stderr, + "%s: actual: type=0x%x, offset=0x%x, size=0x%x\n", + __func__, mem->type, (GLuint) mem->offset, + (GLuint) mem->size); + } + + if (flags & NOUVEAU_MEM_MAPPED) + ret = drmMap(nmesa->driFd, mema.map_handle, mem->size, + &mem->map); + if (ret) { + mem->map = NULL; + nouveau_mem_free(ctx, mem); + mem = NULL; + } + + return mem; +} + +uint32_t nouveau_mem_gpu_offset_get(GLcontext * ctx, nouveau_mem * mem) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + return mem->offset; +} diff --git a/src/mesa/drivers/dri/nouveau/nouveau_mem.h b/src/mesa/drivers/dri/nouveau/nouveau_mem.h new file mode 100644 index 00000000000..6db73f4708e --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_mem.h @@ -0,0 +1,23 @@ +#ifndef __NOUVEAU_MEM_H__ +#define __NOUVEAU_MEM_H__ + +typedef struct nouveau_mem_t { + int type; + uint64_t offset; + uint64_t size; + void *map; +} nouveau_mem; + +extern nouveau_mem *nouveau_mem_alloc(GLcontext *, uint32_t flags, + GLuint size, GLuint align); +extern void nouveau_mem_free(GLcontext *, nouveau_mem *); +extern uint32_t nouveau_mem_gpu_offset_get(GLcontext *, nouveau_mem *); + +extern GLboolean nouveau_memformat_flat_emit(GLcontext *, + nouveau_mem *dst, + nouveau_mem *src, + GLuint dst_offset, + GLuint src_offset, + GLuint size); + +#endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_span.h b/src/mesa/drivers/dri/nouveau/nouveau_span.h index bc39ecd17b5..c4142a10ef4 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_span.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_span.h @@ -30,7 +30,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define __NOUVEAU_SPAN_H__ #include "drirenderbuffer.h" -#include "nouveau_buffers.h" +#include "nouveau_fbo.h" extern void nouveauSpanInitFunctions( GLcontext *ctx ); extern void nouveauSpanSetFunctions(nouveau_renderbuffer *nrb, const GLvisual *vis); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/src/mesa/drivers/dri/nouveau/nouveau_sync.c index 3f5f6d54e9b..abb3088032b 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_sync.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.c @@ -28,11 +28,11 @@ #include "vblank.h" /* for DO_USLEEP */ #include "nouveau_context.h" -#include "nouveau_buffers.h" -#include "nouveau_object.h" #include "nouveau_fifo.h" -#include "nouveau_reg.h" +#include "nouveau_mem.h" #include "nouveau_msg.h" +#include "nouveau_object.h" +#include "nouveau_reg.h" #include "nouveau_sync.h" #define NOTIFIER(__v) \ diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.h b/src/mesa/drivers/dri/nouveau/nouveau_sync.h index 1ff4eca3258..fc37efbe6b2 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_sync.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.h @@ -28,8 +28,6 @@ #ifndef __NOUVEAU_SYNC_H__ #define __NOUVEAU_SYNC_H__ -#include "nouveau_buffers.h" - #define NV_NOTIFIER_SIZE 32 #define NV_NOTIFY_TIME_0 0x00000000 #define NV_NOTIFY_TIME_1 0x00000004