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:
DHrpcs3 2016-03-14 01:28:06 +03:00
parent 10ec26ace8
commit 0f29b5ddb2
7 changed files with 528 additions and 115 deletions

View File

@ -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();
}

View File

@ -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);

View File

@ -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();

View File

@ -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();
};

View File

@ -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)
{

View File

@ -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) };
}

View File

@ -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)
{