+
+
+
+static void
+map_attachment(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ gl_buffer_index buffer)
+{
+ struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
+ struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
+ struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+
+ if (texObj) {
+ /* map texture image (render to texture) */
+ const GLuint level = fb->Attachment[buffer].TextureLevel;
+ const GLuint face = fb->Attachment[buffer].CubeMapFace;
+ const GLuint slice = fb->Attachment[buffer].Zoffset;
+ struct gl_texture_image *texImage = texObj->Image[face][level];
+ if (texImage) {
+ ctx->Driver.MapTextureImage(ctx, texImage, slice,
+ 0, 0, texImage->Width, texImage->Height,
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
+ &srb->Map, &srb->RowStride);
+ }
+ }
+ else if (rb) {
+ /* Map ordinary renderbuffer */
+ ctx->Driver.MapRenderbuffer(ctx, rb,
+ 0, 0, rb->Width, rb->Height,
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
+ &srb->Map, &srb->RowStride);
+ }
+
+ assert(srb->Map);
+}
+
+
+static void
+unmap_attachment(struct gl_context *ctx,
+ struct gl_framebuffer *fb,
+ gl_buffer_index buffer)
+{
+ struct gl_texture_object *texObj = fb->Attachment[buffer].Texture;
+ struct gl_renderbuffer *rb = fb->Attachment[buffer].Renderbuffer;
+ struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+
+ if (texObj) {
+ /* unmap texture image (render to texture) */
+ const GLuint level = fb->Attachment[buffer].TextureLevel;
+ const GLuint face = fb->Attachment[buffer].CubeMapFace;
+ const GLuint slice = fb->Attachment[buffer].Zoffset;
+ struct gl_texture_image *texImage = texObj->Image[face][level];
+ if (texImage) {
+ ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
+ }
+ }
+ else if (rb) {
+ /* unmap ordinary renderbuffer */
+ ctx->Driver.UnmapRenderbuffer(ctx, rb);
+ }
+
+ srb->Map = NULL;
+}
+
+
+/**
+ * Determine what type to use (ubyte vs. float) for span colors for the
+ * given renderbuffer.
+ * See also _swrast_write_rgba_span().
+ */
+static void
+find_renderbuffer_colortype(struct gl_renderbuffer *rb)
+{
+ struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
+ GLuint rbMaxBits = _mesa_get_format_max_bits(rb->Format);
+ GLenum rbDatatype = _mesa_get_format_datatype(rb->Format);
+
+ if (rbDatatype == GL_UNSIGNED_NORMALIZED && rbMaxBits <= 8) {
+ /* the buffer's values fit in GLubyte values */
+ srb->ColorType = GL_UNSIGNED_BYTE;
+ }
+ else {
+ /* use floats otherwise */
+ srb->ColorType = GL_FLOAT;
+ }
+}
+
+
+/**
+ * Map the renderbuffers we'll use for tri/line/point rendering.
+ */
+void
+_swrast_map_renderbuffers(struct gl_context *ctx)
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *depthRb, *stencilRb;
+ GLuint buf;
+
+ depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
+ if (depthRb) {
+ /* map depth buffer */
+ map_attachment(ctx, fb, BUFFER_DEPTH);
+ }
+
+ stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
+ if (stencilRb && stencilRb != depthRb) {
+ /* map stencil buffer */
+ map_attachment(ctx, fb, BUFFER_STENCIL);
+ }
+
+ for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
+ if (fb->_ColorDrawBufferIndexes[buf] >= 0) {
+ map_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]);
+ find_renderbuffer_colortype(fb->_ColorDrawBuffers[buf]);
+ }
+ }
+}
+
+
+/**
+ * Unmap renderbuffers after rendering.
+ */
+void
+_swrast_unmap_renderbuffers(struct gl_context *ctx)
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *depthRb, *stencilRb;
+ GLuint buf;
+
+ depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
+ if (depthRb) {
+ /* map depth buffer */
+ unmap_attachment(ctx, fb, BUFFER_DEPTH);
+ }
+
+ stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
+ if (stencilRb && stencilRb != depthRb) {
+ /* map stencil buffer */
+ unmap_attachment(ctx, fb, BUFFER_STENCIL);
+ }
+
+ for (buf = 0; buf < fb->_NumColorDrawBuffers; buf++) {
+ if (fb->_ColorDrawBufferIndexes[buf] >= 0) {
+ unmap_attachment(ctx, fb, fb->_ColorDrawBufferIndexes[buf]);
+ }
+ }
+}