static GLboolean compatible_resolve_formats(const struct gl_renderbuffer *readRb, const struct gl_renderbuffer *drawRb) { GLenum readFormat, drawFormat; /* The simple case where we know the backing Mesa formats are the same. */ if (_mesa_get_srgb_format_linear(readRb->Format) == _mesa_get_srgb_format_linear(drawRb->Format)) { return GL_TRUE; } /* The Mesa formats are different, so we must check whether the internal * formats are compatible. * * Under some circumstances, the user may request e.g. two GL_RGBA8 * textures and get two entirely different Mesa formats like RGBA8888 and * ARGB8888. Drivers behaving like that should be able to cope with * non-matching formats by themselves, because it's not the user's fault. * * Blits between linear and sRGB formats are also allowed. */ readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat); drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat); readFormat = _mesa_get_linear_internalformat(readFormat); drawFormat = _mesa_get_linear_internalformat(drawFormat); if (readFormat == drawFormat) { return GL_TRUE; } return GL_FALSE; }
static GLboolean compatible_resolve_formats(const struct gl_renderbuffer *readRb, const struct gl_renderbuffer *drawRb) { GLenum readFormat, drawFormat; /* This checks whether the internal formats are compatible rather than the * Mesa format for two reasons: * * • Under some circumstances, the user may request e.g. two GL_RGBA8 * textures and get two entirely different Mesa formats like RGBA8888 and * ARGB8888. Drivers behaving like that should be able to cope with * non-matching formats by themselves, because it's not the user's fault. * * • Picking two different internal formats can end up with the same Mesa * format. For example the driver might be simulating GL_RGB textures * with GL_RGBA internally and in that case both internal formats would * end up with RGBA8888. * * This function is used to generate a GL error according to the spec so in * both cases we want to be looking at the application-level format, which * is InternalFormat. * * Blits between linear and sRGB formats are also allowed. */ readFormat = _mesa_get_nongeneric_internalformat(readRb->InternalFormat); drawFormat = _mesa_get_nongeneric_internalformat(drawRb->InternalFormat); readFormat = _mesa_get_linear_internalformat(readFormat); drawFormat = _mesa_get_linear_internalformat(drawFormat); if (readFormat == drawFormat) { return GL_TRUE; } return GL_FALSE; }
/** * gl_renderbuffer::AllocStorage() * This is called to allocate the original drawing surface, and * during window resize. */ static GLboolean st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = st->pipe->screen; struct st_renderbuffer *strb = st_renderbuffer(rb); enum pipe_format format = PIPE_FORMAT_NONE; struct pipe_surface surf_tmpl; struct pipe_resource templ; /* init renderbuffer fields */ strb->Base.Width = width; strb->Base.Height = height; strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); strb->defined = GL_FALSE; /* undefined contents now */ if (strb->software) { return st_renderbuffer_alloc_sw_storage(ctx, rb, internalFormat, width, height); } /* Free the old surface and texture */ pipe_surface_reference( &strb->surface, NULL ); pipe_resource_reference( &strb->texture, NULL ); /* If an sRGB framebuffer is unsupported, sRGB formats behave like linear * formats. */ if (!ctx->Extensions.EXT_framebuffer_sRGB) { internalFormat = _mesa_get_linear_internalformat(internalFormat); } /* Handle multisample renderbuffers first. * * From ARB_framebuffer_object: * If <samples> is zero, then RENDERBUFFER_SAMPLES is set to zero. * Otherwise <samples> represents a request for a desired minimum * number of samples. Since different implementations may support * different sample counts for multisampled rendering, the actual * number of samples allocated for the renderbuffer image is * implementation dependent. However, the resulting value for * RENDERBUFFER_SAMPLES is guaranteed to be greater than or equal * to <samples> and no more than the next larger sample count supported * by the implementation. * * So let's find the supported number of samples closest to NumSamples. * (NumSamples == 1) is treated the same as (NumSamples == 0). */ if (rb->NumSamples > 1) { unsigned i; for (i = rb->NumSamples; i <= ctx->Const.MaxSamples; i++) { format = st_choose_renderbuffer_format(st, internalFormat, i); if (format != PIPE_FORMAT_NONE) { rb->NumSamples = i; break; } } } else { format = st_choose_renderbuffer_format(st, internalFormat, 0); } /* Not setting gl_renderbuffer::Format here will cause * FRAMEBUFFER_UNSUPPORTED and ValidateFramebuffer will not be called. */ if (format == PIPE_FORMAT_NONE) { return GL_TRUE; } strb->Base.Format = st_pipe_format_to_mesa_format(format); if (width == 0 || height == 0) { /* if size is zero, nothing to allocate */ return GL_TRUE; } /* Setup new texture template. */ memset(&templ, 0, sizeof(templ)); templ.target = st->internal_target; templ.format = format; templ.width0 = width; templ.height0 = height; templ.depth0 = 1; templ.array_size = 1; templ.nr_samples = rb->NumSamples; if (util_format_is_depth_or_stencil(format)) { templ.bind = PIPE_BIND_DEPTH_STENCIL; } else if (strb->Base.Name != 0) { /* this is a user-created renderbuffer */ templ.bind = PIPE_BIND_RENDER_TARGET; } else { /* this is a window-system buffer */ templ.bind = (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET); } strb->texture = screen->resource_create(screen, &templ); if (!strb->texture) return FALSE; u_surface_default_template(&surf_tmpl, strb->texture); strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl); if (strb->surface) { assert(strb->surface->texture); assert(strb->surface->format); assert(strb->surface->width == width); assert(strb->surface->height == height); } return strb->surface != NULL; }