mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-14 01:27:00 +00:00
implemented nv3089_image_in using opengl
implemented support 1D & 3D textures fixed regions relocation use liner filter on buffers blit minor fixes
This commit is contained in:
parent
10ec26ace8
commit
0f29b5ddb2
@ -945,10 +945,308 @@ bool nv4097_clear_surface(u32 arg, GLGSRender* renderer)
|
||||
return true;
|
||||
}
|
||||
|
||||
void scale_texture(gl::texture& dst, gl::texture::sized_internal_format dst_format, size2i dst_size, const gl::texture& src, position2i point, size2i src_size)
|
||||
{
|
||||
dst.bind();
|
||||
|
||||
if (dst.get_target() == gl::texture::target::texture1D)
|
||||
{
|
||||
glTexStorage1D((GLenum)dst.get_target(), 1, (GLenum)dst_format, dst_size.width);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexStorage2D((GLenum)dst.get_target(), 1, (GLenum)dst_format, dst_size.width, dst_size.height);
|
||||
}
|
||||
|
||||
gl::fbo src_fbo, dst_fbo;
|
||||
src_fbo.create();
|
||||
dst_fbo.create();
|
||||
|
||||
dst_fbo.color = dst;
|
||||
src_fbo.color = src;
|
||||
|
||||
src_fbo.blit(dst_fbo, areai{ point.x, point.y, src_size.width, src_size.height }, coordi{ {}, dst_size }, gl::buffers::color, gl::filter::linear);
|
||||
}
|
||||
|
||||
bool nv3089_image_in(u32 arg, GLGSRender* renderer)
|
||||
{
|
||||
//TODO
|
||||
return false;
|
||||
u32 operation = rsx::method_registers[NV3089_SET_OPERATION];
|
||||
|
||||
u32 clip_x = rsx::method_registers[NV3089_CLIP_POINT] & 0xffff;
|
||||
u32 clip_y = rsx::method_registers[NV3089_CLIP_POINT] >> 16;
|
||||
u32 clip_w = rsx::method_registers[NV3089_CLIP_SIZE] & 0xffff;
|
||||
u32 clip_h = rsx::method_registers[NV3089_CLIP_SIZE] >> 16;
|
||||
|
||||
u32 out_x = rsx::method_registers[NV3089_IMAGE_OUT_POINT] & 0xffff;
|
||||
u32 out_y = rsx::method_registers[NV3089_IMAGE_OUT_POINT] >> 16;
|
||||
u32 out_w = rsx::method_registers[NV3089_IMAGE_OUT_SIZE] & 0xffff;
|
||||
u32 out_h = rsx::method_registers[NV3089_IMAGE_OUT_SIZE] >> 16;
|
||||
|
||||
u16 in_w = rsx::method_registers[NV3089_IMAGE_IN_SIZE];
|
||||
u16 in_h = rsx::method_registers[NV3089_IMAGE_IN_SIZE] >> 16;
|
||||
u16 in_pitch = rsx::method_registers[NV3089_IMAGE_IN_FORMAT];
|
||||
u8 in_origin = rsx::method_registers[NV3089_IMAGE_IN_FORMAT] >> 16;
|
||||
u8 in_inter = rsx::method_registers[NV3089_IMAGE_IN_FORMAT] >> 24;
|
||||
u32 src_color_format = rsx::method_registers[NV3089_SET_COLOR_FORMAT];
|
||||
|
||||
u32 context_surface = rsx::method_registers[NV3089_SET_CONTEXT_SURFACE];
|
||||
|
||||
f32 scale_x = 1048576.f / rsx::method_registers[NV3089_DS_DX];
|
||||
f32 scale_y = 1048576.f / rsx::method_registers[NV3089_DT_DY];
|
||||
|
||||
f32 in_x = (arg & 0xffff) / 16.f;
|
||||
f32 in_y = (arg >> 16) / 16.f;
|
||||
|
||||
if (in_w <= 64 || in_h <= 64)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(in_origin != CELL_GCM_TRANSFER_ORIGIN_CORNER)
|
||||
{
|
||||
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown origin (%d)", in_origin);
|
||||
}
|
||||
|
||||
if (in_inter != CELL_GCM_TRANSFER_INTERPOLATOR_ZOH && in_inter != CELL_GCM_TRANSFER_INTERPOLATOR_FOH)
|
||||
{
|
||||
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown inter (%d)", in_inter);
|
||||
}
|
||||
|
||||
if (operation != CELL_GCM_TRANSFER_OPERATION_SRCCOPY)
|
||||
{
|
||||
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unimplemented operation (%d)", operation);
|
||||
return false;
|
||||
}
|
||||
|
||||
const u32 src_offset = rsx::method_registers[NV3089_IMAGE_IN_OFFSET];
|
||||
const u32 src_dma = rsx::method_registers[NV3089_SET_CONTEXT_DMA_IMAGE];
|
||||
|
||||
u32 dst_offset;
|
||||
u32 dst_dma = 0;
|
||||
u16 dst_color_format;
|
||||
u32 out_pitch = 0;
|
||||
u32 out_aligment = 64;
|
||||
|
||||
switch (context_surface)
|
||||
{
|
||||
case CELL_GCM_CONTEXT_SURFACE2D:
|
||||
dst_dma = rsx::method_registers[NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN];
|
||||
dst_offset = rsx::method_registers[NV3062_SET_OFFSET_DESTIN];
|
||||
dst_color_format = rsx::method_registers[NV3062_SET_COLOR_FORMAT];
|
||||
out_pitch = rsx::method_registers[NV3062_SET_PITCH] >> 16;
|
||||
out_aligment = rsx::method_registers[NV3062_SET_PITCH] & 0xffff;
|
||||
break;
|
||||
|
||||
case CELL_GCM_CONTEXT_SWIZZLE2D:
|
||||
dst_dma = rsx::method_registers[NV309E_SET_CONTEXT_DMA_IMAGE];
|
||||
dst_offset = rsx::method_registers[NV309E_SET_OFFSET];
|
||||
dst_color_format = rsx::method_registers[NV309E_SET_FORMAT];
|
||||
break;
|
||||
|
||||
default:
|
||||
//LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown m_context_surface (0x%x)", rsx::method_registers[NV3089_SET_CONTEXT_SURFACE]);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dst_color_format != CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 &&
|
||||
dst_color_format != CELL_GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (src_color_format != CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 &&
|
||||
src_color_format != CELL_GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
u32 in_bpp = src_color_format == CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 ? 2 : 4; // bytes per pixel
|
||||
u32 out_bpp = dst_color_format == CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 ? 2 : 4;
|
||||
|
||||
if (out_pitch == 0)
|
||||
{
|
||||
out_pitch = out_bpp * out_w;
|
||||
}
|
||||
|
||||
if (in_pitch == 0)
|
||||
{
|
||||
in_pitch = in_bpp * in_w;
|
||||
}
|
||||
|
||||
if (clip_w > out_w)
|
||||
{
|
||||
clip_w = out_w;
|
||||
}
|
||||
|
||||
if (clip_h > out_h)
|
||||
{
|
||||
clip_h = out_h;
|
||||
}
|
||||
|
||||
u32 convert_w = u32(scale_x * in_w);
|
||||
u32 convert_h = u32(scale_y * in_h);
|
||||
|
||||
//LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: src = 0x%x, dst = 0x%x", src_address, dst_address);
|
||||
|
||||
rsx::tiled_region src_region = renderer->get_tiled_address(src_offset, src_dma & 0xf);//get_address(src_offset, src_dma);
|
||||
rsx::tiled_region dst_region = renderer->get_tiled_address(dst_offset, dst_dma & 0xf);
|
||||
|
||||
u32 src_x = 0;
|
||||
u32 src_y = 0;
|
||||
|
||||
gl::texture_info src_info{};
|
||||
src_info.start_address = src_region.address;
|
||||
|
||||
if (src_region.tile)
|
||||
{
|
||||
src_x = (src_region.base % src_region.tile->pitch) / in_bpp;
|
||||
src_y = src_region.base / src_region.tile->pitch;
|
||||
|
||||
src_info.width = src_region.tile->pitch / in_bpp;
|
||||
src_info.height = src_region.tile->size / src_region.tile->pitch;
|
||||
src_info.pitch = src_region.tile->pitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_info.width = in_w;
|
||||
src_info.height = in_h;
|
||||
src_info.pitch = in_pitch;
|
||||
}
|
||||
|
||||
src_info.depth = 1;
|
||||
src_info.mipmap = 1;
|
||||
src_info.dimension = src_info.height == 1 ? 1 : 2;
|
||||
|
||||
switch (src_info.dimension)
|
||||
{
|
||||
case 1:
|
||||
if (src_info.width & 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
src_info.target = gl::texture::target::texture1D;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if ((src_info.width | src_info.height) & 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
src_info.target = gl::texture::target::texture2D;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (src_color_format)
|
||||
{
|
||||
case CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5:
|
||||
src_info.format = gl::get_texture_format(CELL_GCM_TEXTURE_R5G6B5);
|
||||
break;
|
||||
|
||||
case CELL_GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8:
|
||||
src_info.format = gl::get_texture_format(CELL_GCM_TEXTURE_A8R8G8B8);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 dst_x = 0;
|
||||
u32 dst_y = 0;
|
||||
|
||||
gl::texture_info dst_info{};
|
||||
dst_info.start_address = dst_region.address;
|
||||
|
||||
if (dst_region.tile)
|
||||
{
|
||||
dst_x = (dst_region.base % dst_region.tile->pitch) / out_bpp;
|
||||
dst_y = dst_region.base / dst_region.tile->pitch;
|
||||
|
||||
dst_info.width = dst_region.tile->pitch / out_bpp;
|
||||
dst_info.height = dst_region.tile->size / dst_region.tile->pitch;
|
||||
dst_info.pitch = dst_region.tile->pitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_info.start_address += out_x * out_bpp + out_y * out_pitch;
|
||||
out_x = 0;
|
||||
out_y = 0;
|
||||
dst_info.width = out_w;
|
||||
dst_info.height = out_h;
|
||||
dst_info.pitch = out_pitch;
|
||||
}
|
||||
|
||||
dst_info.depth = 1;
|
||||
dst_info.mipmap = 1;
|
||||
dst_info.dimension = dst_info.height == 1 ? 1 : 2;
|
||||
|
||||
switch (dst_info.dimension)
|
||||
{
|
||||
case 1:
|
||||
if (dst_info.width & 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dst_info.target = gl::texture::target::texture1D;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if ((dst_info.width | dst_info.height) & 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dst_info.target = gl::texture::target::texture2D;
|
||||
break;
|
||||
}
|
||||
|
||||
dst_info.swizzled = context_surface == CELL_GCM_CONTEXT_SWIZZLE2D;
|
||||
|
||||
switch (dst_color_format)
|
||||
{
|
||||
case CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5:
|
||||
dst_info.format = gl::get_texture_format(CELL_GCM_TEXTURE_R5G6B5);
|
||||
break;
|
||||
|
||||
case CELL_GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8:
|
||||
dst_info.format = gl::get_texture_format(CELL_GCM_TEXTURE_A8R8G8B8);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &src_texture = renderer->texture_cache.entry(src_info, gl::cache_buffers::local);
|
||||
auto &dst_texture = renderer->texture_cache.entry(dst_info);
|
||||
|
||||
dst_texture.ignore(gl::cache_buffers::local);
|
||||
|
||||
u32 src_id = src_texture.view().id();
|
||||
gl::texture tmp;
|
||||
|
||||
if (convert_w != src_info.width || convert_h != src_info.height)
|
||||
{
|
||||
tmp.create(src_info.target);
|
||||
|
||||
__glcheck scale_texture(tmp, src_info.format.internal_format, { (int)convert_w, (int)convert_h },
|
||||
src_texture.view(), { (int)src_x + int(in_x), (int)src_y + int(in_y) }, { int(src_x + in_w), int(src_y + in_h) });
|
||||
|
||||
src_id = tmp.id();
|
||||
|
||||
src_x = 0;
|
||||
src_y = 0;
|
||||
}
|
||||
|
||||
__glcheck glCopyImageSubData(
|
||||
src_id, (GLenum)src_info.target, 0, src_x, src_y, 0,
|
||||
dst_texture.view().id(), (GLenum)dst_info.target, 0, dst_x + out_x, dst_y + out_y, 0,
|
||||
clip_w, clip_h, 1);
|
||||
dst_texture.invalidate(gl::cache_buffers::host);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
using rsx_method_impl_t = bool(*)(u32, GLGSRender*);
|
||||
@ -956,7 +1254,7 @@ using rsx_method_impl_t = bool(*)(u32, GLGSRender*);
|
||||
static const std::unordered_map<u32, rsx_method_impl_t> g_gl_method_tbl =
|
||||
{
|
||||
{ NV4097_CLEAR_SURFACE, nv4097_clear_surface },
|
||||
//{ NV3089_IMAGE_IN, nv3089_image_in },
|
||||
{ NV3089_IMAGE_IN, nv3089_image_in },
|
||||
};
|
||||
|
||||
bool GLGSRender::do_method(u32 cmd, u32 arg)
|
||||
@ -1142,21 +1440,32 @@ u32 surface_format_to_texture_format(rsx::surface_color_format format)
|
||||
return CELL_GCM_TEXTURE_A8R8G8B8;
|
||||
}
|
||||
|
||||
gl::texture_info surface_info(rsx::surface_color_format format, u32 offset, u32 location, u32 width, u32 height, u32 pitch)
|
||||
gl::texture_info surface_info(rsx::thread &rsx, rsx::surface_color_format format, u32 offset, u32 location, u32 width, u32 height, u32 pitch)
|
||||
{
|
||||
gl::texture_info info{};
|
||||
info.format = gl::get_texture_format(surface_format_to_texture_format(format));
|
||||
|
||||
rsx::tiled_region region = rsx.get_tiled_address(offset, location);
|
||||
|
||||
if (region.tile && region.base == 0)
|
||||
{
|
||||
info.width = region.tile->pitch / info.format.bpp;
|
||||
info.height = region.tile->size / region.tile->pitch;
|
||||
info.pitch = region.tile->pitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.width = width;
|
||||
info.height = height;
|
||||
info.pitch = pitch;
|
||||
}
|
||||
|
||||
info.width = width;
|
||||
info.height = height;
|
||||
info.depth = 1;
|
||||
info.pitch = pitch;
|
||||
info.target = gl::texture::target::texture2D;
|
||||
info.dimension = 2;
|
||||
info.start_address = rsx::get_address(offset, location);
|
||||
info.start_address = region.address;
|
||||
info.mipmap = 1;
|
||||
|
||||
info.format = gl::get_texture_format(surface_format_to_texture_format(format));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@ -1209,7 +1518,7 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
u32 pitch = rsx::method_registers[mr_color_pitch[index]];
|
||||
bool swizzled = m_surface.type == CELL_GCM_SURFACE_SWIZZLE;
|
||||
|
||||
gl::texture_info info = surface_info(m_surface.color_format, offset, location, m_surface.width, m_surface.height, pitch);
|
||||
gl::texture_info info = surface_info(*this, m_surface.color_format, offset, location, m_surface.width, m_surface.height, pitch);
|
||||
|
||||
info.swizzled = swizzled;
|
||||
|
||||
@ -1248,12 +1557,24 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
|
||||
gl::texture_info info{};
|
||||
|
||||
info.width = m_surface.width;
|
||||
info.height = m_surface.height;
|
||||
rsx::tiled_region region = get_tiled_address(offset, location);
|
||||
|
||||
if (region.tile && region.base == 0)
|
||||
{
|
||||
info.width = region.tile->pitch / info.format.bpp;
|
||||
info.height = region.tile->size / region.tile->pitch;
|
||||
info.pitch = region.tile->pitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
info.width = m_surface.width;
|
||||
info.height = m_surface.height;
|
||||
info.pitch = pitch;
|
||||
}
|
||||
|
||||
info.depth = 1;
|
||||
info.pitch = pitch;
|
||||
info.dimension = 2;
|
||||
info.start_address = rsx::get_address(offset, location);
|
||||
info.start_address = region.address;
|
||||
info.target = gl::texture::target::texture2D;
|
||||
info.format.bpp = bpp;
|
||||
info.mipmap = 1;
|
||||
@ -1341,7 +1662,7 @@ void GLGSRender::flip(int buffer)
|
||||
glDisable(GL_LOGIC_OP);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
gl::cached_texture& texture = texture_cache.entry(surface_info(rsx::surface_color_format::a8r8g8b8, gcm_buffers[buffer].offset,
|
||||
gl::cached_texture& texture = texture_cache.entry(surface_info(*this, rsx::surface_color_format::a8r8g8b8, gcm_buffers[buffer].offset,
|
||||
CELL_GCM_LOCATION_LOCAL, buffer_width, buffer_height, buffer_pitch), gl::cache_buffers::local);
|
||||
|
||||
//std::lock_guard<gl::cached_texture> lock(texture);
|
||||
@ -1382,9 +1703,11 @@ void GLGSRender::flip(int buffer)
|
||||
|
||||
gl::screen.clear(gl::buffers::color_depth_stencil);
|
||||
|
||||
__glcheck m_flip_fbo.blit(gl::screen, screen_area, areai(aspect_ratio).flipped_vertical());
|
||||
__glcheck m_flip_fbo.blit(gl::screen, screen_area, areai(aspect_ratio).flipped_vertical(), gl::buffers::color, gl::filter::linear);
|
||||
|
||||
m_frame->flip(m_context);
|
||||
|
||||
texture_cache.update_protection();
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,6 +177,7 @@ OPENGL_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC, CompressedTexSubImage1D);
|
||||
OPENGL_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, CompressedTexSubImage2D);
|
||||
OPENGL_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, CompressedTexSubImage3D);
|
||||
OPENGL_PROC(PFNGLCLEARTEXIMAGEPROC, ClearTexImage);
|
||||
OPENGL_PROC(PFNGLTEXSUBIMAGE3DPROC, TexSubImage3D);
|
||||
|
||||
//ARB_Copy_Image
|
||||
OPENGL_PROC(PFNGLCOPYIMAGESUBDATAPROC, CopyImageSubData);
|
||||
|
@ -17,7 +17,14 @@ namespace gl
|
||||
{
|
||||
void cached_texture::read()
|
||||
{
|
||||
cached_texture* found_texture = nullptr;
|
||||
struct capability_texture
|
||||
{
|
||||
positioni src_pos;
|
||||
positioni dst_pos;
|
||||
cached_texture* texture;
|
||||
};
|
||||
|
||||
std::vector<capability_texture> found_textures;
|
||||
u32 texture_size = info.size();
|
||||
|
||||
m_parent_region->for_each(info.start_address, texture_size, [&](cached_texture& texture)
|
||||
@ -27,24 +34,91 @@ namespace gl
|
||||
return;
|
||||
}
|
||||
|
||||
if (texture.info.start_address != info.start_address ||
|
||||
texture.info.pitch != info.pitch ||
|
||||
texture.info.height < info.height ||
|
||||
texture.info.width < info.width)
|
||||
if (texture.info.pitch != info.pitch || texture.info.format.bpp != info.format.bpp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
found_texture = &texture;
|
||||
capability_texture texture_info{};
|
||||
|
||||
if (texture.info.start_address < info.start_address)
|
||||
{
|
||||
if (texture.info.dimension > 2)
|
||||
return;
|
||||
|
||||
u32 diff = info.start_address - texture.info.start_address;
|
||||
|
||||
texture_info.src_pos.y = diff / info.pitch;
|
||||
texture_info.src_pos.x = (diff % info.pitch) / info.format.bpp;
|
||||
|
||||
//texture.sync(cache_buffers::host);
|
||||
}
|
||||
else if (texture.info.start_address > info.start_address)
|
||||
{
|
||||
if (info.dimension > 2)
|
||||
return;
|
||||
|
||||
u32 diff = texture.info.start_address - info.start_address;
|
||||
|
||||
texture_info.dst_pos.y = diff / info.pitch;
|
||||
texture_info.dst_pos.x = (diff % info.pitch) / info.format.bpp;
|
||||
|
||||
//texture.sync(gl::cache_buffers::host);
|
||||
}
|
||||
|
||||
texture_info.texture = &texture;
|
||||
found_textures.push_back(texture_info);
|
||||
});
|
||||
|
||||
if (found_texture)
|
||||
u32 covered_width = 0, covered_height = 0, covered_depth = 0;
|
||||
|
||||
while (found_textures.size() > 1)
|
||||
{
|
||||
//read from local
|
||||
__glcheck glCopyImageSubData(
|
||||
found_texture->gl_name, (GLenum)found_texture->info.target, 0, 0, 0, 0,
|
||||
gl_name, (GLenum)info.target, 0, 0, 0, 0,
|
||||
info.width, info.height, info.depth);
|
||||
bool found = false;
|
||||
|
||||
for (auto& tex : found_textures)
|
||||
{
|
||||
if (tex.dst_pos.x == covered_width)
|
||||
{
|
||||
covered_width += tex.texture->info.width;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (tex.dst_pos.y == covered_height)
|
||||
{
|
||||
covered_height += tex.texture->info.height;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (0 == covered_depth)
|
||||
{
|
||||
covered_depth += tex.texture->info.depth;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (covered_width < info.width || covered_height < info.height || covered_depth < info.depth)
|
||||
{
|
||||
found_textures.clear();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_textures.empty())
|
||||
{
|
||||
//read from locals
|
||||
|
||||
for (auto &tex : found_textures)
|
||||
{
|
||||
__glcheck glCopyImageSubData(
|
||||
tex.texture->gl_name, (GLenum)tex.texture->info.target, 0, tex.src_pos.x, tex.src_pos.y, 0,
|
||||
gl_name, (GLenum)info.target, 0, tex.dst_pos.x, tex.dst_pos.y, 0,
|
||||
std::min(tex.texture->info.width, info.width), std::min(tex.texture->info.height, info.height), std::min(tex.texture->info.depth, tex.texture->info.depth));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -53,6 +127,7 @@ namespace gl
|
||||
m_parent_region->for_each(info.start_address, texture_size, [](cached_texture& texture)
|
||||
{
|
||||
texture.sync(gl::cache_buffers::host);
|
||||
//texture.invalidate(gl::cache_buffers::local);
|
||||
});
|
||||
|
||||
bind();
|
||||
@ -101,20 +176,48 @@ namespace gl
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_depth.id());
|
||||
|
||||
__glcheck glTexSubImage2D((GLenum)info.target, 0, 0, 0, info.width, info.height,
|
||||
(GLenum)info.format.format, (GLenum)info.format.type, nullptr);
|
||||
|
||||
switch (info.dimension)
|
||||
{
|
||||
case 1: __glcheck glTexSubImage1D((GLenum)info.target, 0, 0, info.width, (GLenum)info.format.format, (GLenum)info.format.type, nullptr); break;
|
||||
case 2: __glcheck glTexSubImage2D((GLenum)info.target, 0, 0, 0, info.width, info.height, (GLenum)info.format.format, (GLenum)info.format.type, nullptr); break;
|
||||
case 3: __glcheck glTexSubImage3D((GLenum)info.target, 0, 0, 0, 0, info.width, info.height, info.depth, (GLenum)info.format.format, (GLenum)info.format.type, nullptr); break;
|
||||
}
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
else if (info.compressed_size)
|
||||
{
|
||||
__glcheck glCompressedTexSubImage2D((GLenum)info.target, 0,
|
||||
0, 0, info.width, info.height,
|
||||
(GLenum)info.format.internal_format,
|
||||
info.compressed_size, vm::base_priv(info.start_address));
|
||||
switch (info.dimension)
|
||||
{
|
||||
case 1:
|
||||
__glcheck glCompressedTexSubImage1D((GLenum)info.target, 0,
|
||||
0, info.width,
|
||||
(GLenum)info.format.internal_format,
|
||||
info.compressed_size, vm::base_priv(info.start_address));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
__glcheck glCompressedTexSubImage2D((GLenum)info.target, 0,
|
||||
0, 0, info.width, info.height,
|
||||
(GLenum)info.format.internal_format,
|
||||
info.compressed_size, vm::base_priv(info.start_address));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
__glcheck glCompressedTexSubImage3D((GLenum)info.target, 0,
|
||||
0, 0, 0, info.width, info.height, info.depth,
|
||||
(GLenum)info.format.internal_format,
|
||||
info.compressed_size, vm::base_priv(info.start_address));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.dimension > 2)
|
||||
{
|
||||
LOG_ERROR(RSX, "unimplemented reading swizzled %uD texture", info.dimension);
|
||||
}
|
||||
|
||||
void *pixels = vm::base_priv(info.start_address);
|
||||
|
||||
std::unique_ptr<u8[]> linear_pixels;
|
||||
@ -150,8 +253,12 @@ namespace gl
|
||||
.swap_bytes((info.format.flags & gl::texture_flags::swap_bytes) != gl::texture_flags::none)
|
||||
.apply();
|
||||
|
||||
__glcheck glTexSubImage2D((GLenum)info.target, 0, 0, 0, info.width, info.height,
|
||||
(GLenum)info.format.format, (GLenum)info.format.type, pixels);
|
||||
switch (info.dimension)
|
||||
{
|
||||
case 1: __glcheck glTexSubImage1D((GLenum)info.target, 0, 0, info.width, (GLenum)info.format.format, (GLenum)info.format.type, pixels); break;
|
||||
case 2: __glcheck glTexSubImage2D((GLenum)info.target, 0, 0, 0, info.width, info.height, (GLenum)info.format.format, (GLenum)info.format.type, pixels); break;
|
||||
case 3: __glcheck glTexSubImage3D((GLenum)info.target, 0, 0, 0, 0, info.width, info.height, info.depth, (GLenum)info.format.format, (GLenum)info.format.type, pixels); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (info.mipmap > 1)
|
||||
@ -351,16 +458,6 @@ namespace gl
|
||||
return cache_access::none;
|
||||
}
|
||||
|
||||
void cached_texture::lock()
|
||||
{
|
||||
m_parent_region->lock();
|
||||
}
|
||||
|
||||
void cached_texture::unlock()
|
||||
{
|
||||
m_parent_region->unlock();
|
||||
}
|
||||
|
||||
void cached_texture::bind(uint index) const
|
||||
{
|
||||
if (index != ~0u)
|
||||
@ -378,7 +475,15 @@ namespace gl
|
||||
glGenTextures(1, &gl_name);
|
||||
|
||||
bind();
|
||||
__glcheck glTexStorage2D((GLenum)info.target, info.mipmap, (GLenum)info.format.internal_format, info.width, info.height);
|
||||
|
||||
switch (info.dimension)
|
||||
{
|
||||
case 1: __glcheck glTexStorage1D((GLenum)info.target, info.mipmap, (GLenum)info.format.internal_format, info.width); break;
|
||||
case 2: __glcheck glTexStorage2D((GLenum)info.target, info.mipmap, (GLenum)info.format.internal_format, info.width, info.height); break;
|
||||
case 3: __glcheck glTexStorage3D((GLenum)info.target, info.mipmap, (GLenum)info.format.internal_format, info.width, info.height, info.depth); break;
|
||||
default:
|
||||
throw EXCEPTION("bad dimension %d", info.dimension);
|
||||
}
|
||||
//__glcheck glClearTexImage(gl_name, 0, (GLenum)info.format.format, (GLenum)info.format.type, nullptr);
|
||||
}
|
||||
|
||||
@ -501,10 +606,12 @@ namespace gl
|
||||
for (auto &texture : region.m_textures)
|
||||
{
|
||||
texture.second.parent(this);
|
||||
if (!m_textures.emplace(texture).second)
|
||||
{
|
||||
throw EXCEPTION("");
|
||||
}
|
||||
}
|
||||
|
||||
m_textures.insert(region.m_textures.begin(), region.m_textures.end());
|
||||
|
||||
if (region.start_address < start_address)
|
||||
{
|
||||
pages_count += (start_address - region.start_address) / vm::page_size;
|
||||
@ -512,7 +619,9 @@ namespace gl
|
||||
}
|
||||
else
|
||||
{
|
||||
pages_count = (region.start_address + region.pages_count - start_address) / vm::page_size;
|
||||
//[start_address, region.start_address + region.pages_count * vm::page_size)
|
||||
|
||||
pages_count = (region.start_address + region.pages_count * vm::page_size - start_address) / vm::page_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -558,16 +667,6 @@ namespace gl
|
||||
m_textures.clear();
|
||||
}
|
||||
|
||||
void protected_region::lock()
|
||||
{
|
||||
m_mtx.lock();
|
||||
}
|
||||
|
||||
void protected_region::unlock()
|
||||
{
|
||||
m_mtx.unlock();
|
||||
}
|
||||
|
||||
cached_texture &texture_cache::entry(const texture_info &info, cache_buffers sync)
|
||||
{
|
||||
u32 aligned_address;
|
||||
@ -595,30 +694,24 @@ namespace gl
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<protected_region*> regions = find_regions(aligned_address, aligned_size);
|
||||
std::vector<std::list<protected_region>::iterator> regions = find_regions(aligned_address, aligned_size);
|
||||
protected_region *region;
|
||||
|
||||
if (regions.empty())
|
||||
{
|
||||
region = &m_protected_regions[aligned_address];
|
||||
m_protected_regions.emplace_back();
|
||||
region = &m_protected_regions.back();
|
||||
region->pages_count = aligned_size / vm::page_size;
|
||||
region->start_address = aligned_address;
|
||||
}
|
||||
else
|
||||
{
|
||||
region = regions[0];
|
||||
|
||||
std::vector<u32> remove_addresses;
|
||||
region = &*regions[0];
|
||||
|
||||
for (std::size_t index = 1; index < regions.size(); ++index)
|
||||
{
|
||||
region->combine(*regions[index]);
|
||||
remove_addresses.push_back(regions[index]->start_address);
|
||||
}
|
||||
|
||||
for (u32 address : remove_addresses)
|
||||
{
|
||||
m_protected_regions.erase(address);
|
||||
m_protected_regions.erase(regions[index]);
|
||||
}
|
||||
|
||||
if (region->start_address > aligned_address)
|
||||
@ -647,37 +740,37 @@ namespace gl
|
||||
{
|
||||
for (auto& entry : m_protected_regions)
|
||||
{
|
||||
if (entry.first > address)
|
||||
if (entry.start_address > address)
|
||||
{
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (address >= entry.first && address < entry.first + entry.second.size())
|
||||
if (address >= entry.start_address && address < entry.start_address + entry.size())
|
||||
{
|
||||
return &entry.second;
|
||||
return &entry;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<protected_region*> texture_cache::find_regions(u32 address, u32 size)
|
||||
std::vector<std::list<protected_region>::iterator> texture_cache::find_regions(u32 address, u32 size)
|
||||
{
|
||||
std::vector<protected_region *> result;
|
||||
std::vector<std::list<protected_region>::iterator> result;
|
||||
|
||||
for (auto& entry : m_protected_regions)
|
||||
for (auto it = m_protected_regions.begin(); it != m_protected_regions.end(); ++it)
|
||||
{
|
||||
if (entry.first >= address + size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (entry.first + entry.second.size() <= address)
|
||||
if (it->start_address >= address + size)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.push_back(&entry.second);
|
||||
if (it->start_address + it->size() <= address)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.push_back(it);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -687,7 +780,7 @@ namespace gl
|
||||
{
|
||||
for (auto& entry : m_protected_regions)
|
||||
{
|
||||
entry.second.protect();
|
||||
entry.protect();
|
||||
}
|
||||
}
|
||||
|
||||
@ -695,7 +788,7 @@ namespace gl
|
||||
{
|
||||
for (auto& entry : m_protected_regions)
|
||||
{
|
||||
entry.second.clear();
|
||||
entry.clear();
|
||||
}
|
||||
|
||||
m_protected_regions.clear();
|
||||
|
@ -108,9 +108,6 @@ namespace gl
|
||||
|
||||
cache_access requires_protection() const;
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
protected:
|
||||
void create();
|
||||
void remove();
|
||||
@ -126,9 +123,7 @@ namespace gl
|
||||
|
||||
private:
|
||||
std::unordered_map<texture_info, cached_texture, fnv_1a_hasher, bitwise_equals> m_textures;
|
||||
|
||||
u32 m_current_protection = 0;
|
||||
std::mutex m_mtx;
|
||||
|
||||
public:
|
||||
u32 size() const
|
||||
@ -150,19 +145,16 @@ namespace gl
|
||||
cached_texture& add(const texture_info& info);
|
||||
|
||||
void clear();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
class texture_cache
|
||||
{
|
||||
std::map<u32, protected_region> m_protected_regions;
|
||||
std::list<protected_region> m_protected_regions;
|
||||
|
||||
public:
|
||||
cached_texture &entry(const texture_info &info, cache_buffers sync = cache_buffers::none);
|
||||
protected_region *find_region(u32 address);
|
||||
std::vector<protected_region*> find_regions(u32 address, u32 size);
|
||||
std::vector<std::list<protected_region>::iterator> find_regions(u32 address, u32 size);
|
||||
void update_protection();
|
||||
void clear();
|
||||
};
|
||||
|
@ -178,9 +178,13 @@ void rsx::gl_texture::bind(gl::texture_cache& cache, rsx::texture& tex)
|
||||
info.swizzled = is_swizzled;
|
||||
info.target = target;
|
||||
info.mipmap = target != gl::texture::target::texture_rectangle ? tex.mipmap() : 1;
|
||||
info.min_lod = tex.min_lod() >> 8;
|
||||
info.max_lod = tex.max_lod() >> 8;
|
||||
info.lod_bias = tex.bias();
|
||||
|
||||
if (info.mipmap > 1)
|
||||
{
|
||||
info.min_lod = tex.min_lod() >> 8;
|
||||
info.max_lod = tex.max_lod() >> 8;
|
||||
info.lod_bias = tex.bias();
|
||||
}
|
||||
|
||||
if (is_compressed)
|
||||
{
|
||||
|
@ -180,14 +180,12 @@ namespace rsx
|
||||
|
||||
switch (tile->comp)
|
||||
{
|
||||
case CELL_GCM_COMPMODE_C32_2X1:
|
||||
case CELL_GCM_COMPMODE_DISABLED:
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
memcpy(ptr + (offset_y + y) * tile->pitch + offset_x, (u8*)src + pitch * y, pitch);
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case CELL_GCM_COMPMODE_C32_2X1:
|
||||
for (u32 y = 0; y < height; ++y)
|
||||
{
|
||||
@ -200,7 +198,6 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case CELL_GCM_COMPMODE_C32_2X2:
|
||||
for (u32 y = 0; y < height; ++y)
|
||||
{
|
||||
@ -233,14 +230,12 @@ namespace rsx
|
||||
|
||||
switch (tile->comp)
|
||||
{
|
||||
case CELL_GCM_COMPMODE_C32_2X1:
|
||||
case CELL_GCM_COMPMODE_DISABLED:
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
memcpy((u8*)dst + pitch * y, ptr + (offset_y + y) * tile->pitch + offset_x, pitch);
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case CELL_GCM_COMPMODE_C32_2X1:
|
||||
for (u32 y = 0; y < height; ++y)
|
||||
{
|
||||
@ -252,7 +247,6 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case CELL_GCM_COMPMODE_C32_2X2:
|
||||
for (u32 y = 0; y < height; ++y)
|
||||
{
|
||||
@ -845,7 +839,7 @@ namespace rsx
|
||||
|
||||
tiled_region thread::get_tiled_address(u32 offset, u32 location)
|
||||
{
|
||||
u32 address = get_address(offset, location);
|
||||
u32 address;
|
||||
|
||||
GcmTileInfo *tile = find_tile(offset, location);
|
||||
u32 base = 0;
|
||||
@ -855,6 +849,10 @@ namespace rsx
|
||||
base = offset - tile->offset;
|
||||
address = get_address(tile->offset, location);
|
||||
}
|
||||
else
|
||||
{
|
||||
address = get_address(offset, location);
|
||||
}
|
||||
|
||||
return{ address, base, tile, (u8*)vm::base(address) };
|
||||
}
|
||||
|
@ -344,8 +344,8 @@ namespace rsx
|
||||
u8 in_inter = method_registers[NV3089_IMAGE_IN_FORMAT] >> 24;
|
||||
u32 src_color_format = method_registers[NV3089_SET_COLOR_FORMAT];
|
||||
|
||||
f32 in_x = (method_registers[NV3089_IMAGE_IN] & 0xffff) / 16.f;
|
||||
f32 in_y = (method_registers[NV3089_IMAGE_IN] >> 16) / 16.f;
|
||||
f32 in_x = (arg & 0xffff) / 16.f;
|
||||
f32 in_y = (arg >> 16) / 16.f;
|
||||
|
||||
if (in_origin != CELL_GCM_TRANSFER_ORIGIN_CORNER)
|
||||
{
|
||||
@ -395,7 +395,7 @@ namespace rsx
|
||||
u32 in_bpp = src_color_format == CELL_GCM_TRANSFER_SCALE_FORMAT_R5G6B5 ? 2 : 4; // bytes per pixel
|
||||
u32 out_bpp = dst_color_format == CELL_GCM_TRANSFER_SURFACE_FORMAT_R5G6B5 ? 2 : 4;
|
||||
|
||||
u32 in_offset = u32(in_x * in_bpp + in_pitch * in_y);
|
||||
u32 in_offset = u32(in_x) * u32(in_bpp + in_pitch * in_y);
|
||||
u32 out_offset = out_x * out_bpp + out_pitch * out_y;
|
||||
|
||||
tiled_region src_region = rsx->get_tiled_address(src_offset + in_offset, src_dma & 0xf);//get_address(src_offset, src_dma);
|
||||
@ -473,7 +473,7 @@ namespace rsx
|
||||
if (size > src_region.tile->size - src_region.base)
|
||||
{
|
||||
u32 diff = size - (src_region.tile->size - src_region.base);
|
||||
slice_h -= diff / in_pitch + (diff % in_pitch ? 1 : 0);
|
||||
slice_h -= (diff + in_pitch - 1) / in_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,7 +503,7 @@ namespace rsx
|
||||
}
|
||||
else
|
||||
{
|
||||
if (out_pitch != in_pitch || out_pitch != out_bpp * out_w)
|
||||
if (out_pitch != in_pitch || out_pitch != out_bpp * out_w || in_pitch != in_bpp * in_w)
|
||||
{
|
||||
for (u32 y = 0; y < out_h; ++y)
|
||||
{
|
||||
@ -561,10 +561,12 @@ namespace rsx
|
||||
u8* linear_pixels = pixels_src;
|
||||
u8* swizzled_pixels = temp2.get();
|
||||
|
||||
std::unique_ptr<u8[]> sw_temp;
|
||||
|
||||
// Check and pad texture out if we are given non square texture for swizzle to be correct
|
||||
if (sw_width != out_w || sw_height != out_h)
|
||||
{
|
||||
std::unique_ptr<u8[]> sw_temp(new u8[out_bpp * sw_width * sw_height]);
|
||||
sw_temp.reset(new u8[out_bpp * sw_width * sw_height]);
|
||||
|
||||
switch (out_bpp)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user