diff options
Diffstat (limited to 'src/osd/modules/render/drawd3d.cpp')
-rw-r--r-- | src/osd/modules/render/drawd3d.cpp | 315 |
1 files changed, 181 insertions, 134 deletions
diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp index 0f50cae8d55..4037c9c0bbe 100644 --- a/src/osd/modules/render/drawd3d.cpp +++ b/src/osd/modules/render/drawd3d.cpp @@ -209,6 +209,7 @@ render_primitive_list *renderer_d3d9::get_primitives() } if (m_shaders != nullptr) { + // do not transform primitives (scale, offset) if shaders are enabled, the shaders will handle the transformation window().target()->set_transform_primitives(!m_shaders->enabled()); } return &window().target()->get_primitives(); @@ -419,6 +420,63 @@ d3d_texture_manager::~d3d_texture_manager() { } + +//============================================================ +// d3d_texture_manager::compute_texture_size +//============================================================ + +void d3d_texture_manager::compute_texture_size(int texwidth, int texheight, int* p_width, int* p_height) +{ + int finalheight = texheight; + int finalwidth = texwidth; + + // round width/height up to nearest power of 2 if we need to + if (!(get_texture_caps() & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) + { + // first the width + if (finalwidth & (finalwidth - 1)) + { + finalwidth |= finalwidth >> 1; + finalwidth |= finalwidth >> 2; + finalwidth |= finalwidth >> 4; + finalwidth |= finalwidth >> 8; + finalwidth++; + } + + // then the height + if (finalheight & (finalheight - 1)) + { + finalheight |= finalheight >> 1; + finalheight |= finalheight >> 2; + finalheight |= finalheight >> 4; + finalheight |= finalheight >> 8; + finalheight++; + } + } + + // round up to square if we need to + if (get_texture_caps() & D3DPTEXTURECAPS_SQUAREONLY) + { + if (finalwidth < finalheight) + finalwidth = finalheight; + else + finalheight = finalwidth; + } + + // adjust the aspect ratio if we need to + while (finalwidth < finalheight && finalheight / finalwidth > get_max_texture_aspect()) + { + finalwidth *= 2; + } + while (finalheight < finalwidth && finalwidth / finalheight > get_max_texture_aspect()) + { + finalheight *= 2; + } + + *p_width = finalwidth; + *p_height = finalheight; +} + void d3d_texture_manager::create_resources() { // experimental: load a PNG to use for vector rendering; it is treated @@ -636,8 +694,20 @@ void d3d_texture_manager::update_textures() texture_info *texture = find_texinfo(&prim->texture, prim->flags); if (texture == nullptr) { - // if there isn't one, create a new texture - global_alloc(texture_info(this, &prim->texture, m_renderer->window().prescale(), prim->flags)); + if (m_renderer->get_shaders()->enabled()) + { + // create a new texture without prescale, shaders will handle the prescale + texture = global_alloc(texture_info(this, &prim->texture, 1, prim->flags)); + if (texture != nullptr) + { + m_renderer->get_shaders()->register_texture(prim, texture); + } + } + else + { + // create a new texture + texture = global_alloc(texture_info(this, &prim->texture, m_renderer->window().prescale(), prim->flags)); + } } else { @@ -1631,11 +1701,12 @@ void renderer_d3d9::draw_quad(const render_primitive *prim) float height = prim->bounds.y1 - prim->bounds.y0; // set the texture coordinates - if(texture != nullptr) + if (texture != nullptr) { vec2f& start = texture->get_uvstart(); vec2f& stop = texture->get_uvstop(); vec2f delta = stop - start; + vertex[0].u0 = start.c.x + delta.c.x * prim->texcoords.tl.u; vertex[0].v0 = start.c.y + delta.c.y * prim->texcoords.tl.v; vertex[1].u0 = start.c.x + delta.c.x * prim->texcoords.tr.u; @@ -1888,18 +1959,20 @@ texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* t m_d3dsurface = nullptr; m_d3dfinaltex = nullptr; - // compute the size - compute_size(texsource->width, texsource->height); - // non-screen textures are easy if (!PRIMFLAG_GET_SCREENTEX(flags)) { + // required to compute the size + m_type = TEXTURE_TYPE_PLAIN; + + // compute the size + compute_size(texsource->width, texsource->height); + assert(PRIMFLAG_TEXFORMAT(flags) != TEXFORMAT_YUY16); result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_d3dtex); if (result != D3D_OK) goto error; m_d3dfinaltex = m_d3dtex; - m_type = TEXTURE_TYPE_PLAIN; } // screen textures are allocated differently @@ -1957,23 +2030,22 @@ texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* t m_xprescale = m_yprescale = 1; } - // screen textures with no prescaling are pretty easy + // screen textures with no prescaling are pretty easy and shaders handle prescale itself if (m_xprescale == 1 && m_yprescale == 1) { + // required to compute the size + m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; + + // compute the size + compute_size(texsource->width, texsource->height); + result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex); if (result == D3D_OK) { m_d3dfinaltex = m_d3dtex; - m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; - if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_texture(this)) - { - goto error; - } - break; } } - // screen textures with prescaling require two allocations else { @@ -1981,23 +2053,32 @@ texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* t // (won't work for YUY textures) if (m_texture_manager->is_stretch_supported() && PRIMFLAG_GET_TEXFORMAT(flags) != TEXFORMAT_YUY16) { + // required to compute the size + m_type = TEXTURE_TYPE_SURFACE; + + // compute the size + compute_size(texsource->width, texsource->height); + result = (*d3dintf->device.create_offscreen_plain_surface)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, format, D3DPOOL_DEFAULT, &m_d3dsurface); if (result != D3D_OK) { continue; } - m_type = TEXTURE_TYPE_SURFACE; } - // otherwise, we allocate a dynamic texture for the source else { + // required to compute the size + m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; + + // compute the size + compute_size(texsource->width, texsource->height); + result = (*d3dintf->device.create_texture)(m_renderer->get_device(), m_rawdims.c.x, m_rawdims.c.y, 1, usage, format, pool, &m_d3dtex); if (result != D3D_OK) { continue; } - m_type = m_texture_manager->is_dynamic_supported() ? TEXTURE_TYPE_DYNAMIC : TEXTURE_TYPE_PLAIN; } // for the target surface, we allocate a render target texture @@ -2006,15 +2087,13 @@ texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* t // target surfaces typically cannot be YCbCr, so we always pick RGB in that case D3DFORMAT finalfmt = (format != m_texture_manager->get_yuv_format()) ? format : D3DFMT_A8R8G8B8; + result = (*d3dintf->device.create_texture)(m_renderer->get_device(), scwidth, scheight, 1, D3DUSAGE_RENDERTARGET, finalfmt, D3DPOOL_DEFAULT, &m_d3dfinaltex); if (result == D3D_OK) { - if (m_renderer->get_shaders()->enabled() && !m_renderer->get_shaders()->register_prescaled_texture(this)) - { - goto error; - } break; } + (*d3dintf->texture.release)(m_d3dtex); m_d3dtex = nullptr; } @@ -2024,7 +2103,6 @@ texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* t // copy the data to the texture set_data(texsource, flags); - //texsource->osdhandle = (void*)this; // add us to the texture list if(m_texture_manager->get_texlist() != nullptr) m_texture_manager->get_texlist()->m_prev = this; @@ -2044,63 +2122,6 @@ error: //============================================================ -// texture_info::compute_size_subroutine -//============================================================ - -void texture_info::compute_size_subroutine(int texwidth, int texheight, int* p_width, int* p_height) -{ - int finalheight = texheight; - int finalwidth = texwidth; - - // round width/height up to nearest power of 2 if we need to - if (!(m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) - { - // first the width - if (finalwidth & (finalwidth - 1)) - { - finalwidth |= finalwidth >> 1; - finalwidth |= finalwidth >> 2; - finalwidth |= finalwidth >> 4; - finalwidth |= finalwidth >> 8; - finalwidth++; - } - - // then the height - if (finalheight & (finalheight - 1)) - { - finalheight |= finalheight >> 1; - finalheight |= finalheight >> 2; - finalheight |= finalheight >> 4; - finalheight |= finalheight >> 8; - finalheight++; - } - } - - // round up to square if we need to - if (m_texture_manager->get_texture_caps() & D3DPTEXTURECAPS_SQUAREONLY) - { - if (finalwidth < finalheight) - finalwidth = finalheight; - else - finalheight = finalwidth; - } - - // adjust the aspect ratio if we need to - while (finalwidth < finalheight && finalheight / finalwidth > m_texture_manager->get_max_texture_aspect()) - { - finalwidth *= 2; - } - while (finalheight < finalwidth && finalwidth / finalheight > m_texture_manager->get_max_texture_aspect()) - { - finalheight *= 2; - } - - *p_width = finalwidth; - *p_height = finalheight; -} - - -//============================================================ // texture_info::compute_size //============================================================ @@ -2112,30 +2133,42 @@ void texture_info::compute_size(int texwidth, int texheight) m_xborderpix = 0; m_yborderpix = 0; - // if we're not wrapping, add a 1-2 pixel border on all sides - if (ENABLE_BORDER_PIX && !(m_flags & PRIMFLAG_TEXWRAP_MASK)) + bool shaders_enabled = m_renderer->get_shaders()->enabled(); + bool wrap_texture = (m_flags & PRIMFLAG_TEXWRAP_MASK) == PRIMFLAG_TEXWRAP_MASK; + bool border_texture = ENABLE_BORDER_PIX && !wrap_texture; + bool surface_texture = m_type == TEXTURE_TYPE_SURFACE; + + // skip border when shaders are enabled and we're not creating a surface (UI) texture + if (!shaders_enabled || surface_texture) { - // note we need 2 pixels in X for YUY textures - m_xborderpix = (PRIMFLAG_GET_TEXFORMAT(m_flags) == TEXFORMAT_YUY16) ? 2 : 1; - m_yborderpix = 1; + // if we're not wrapping, add a 1-2 pixel border on all sides + if (border_texture) + { + // note we need 2 pixels in X for YUY textures + m_xborderpix = (PRIMFLAG_GET_TEXFORMAT(m_flags) == TEXFORMAT_YUY16) ? 2 : 1; + m_yborderpix = 1; + } } - // compute final texture size finalwidth += 2 * m_xborderpix; finalheight += 2 * m_yborderpix; - compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight); - - // if we added pixels for the border, and that just barely pushed us over, take it back - if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) + // take texture size as given when shaders are enabled and we're not creating a surface (UI) texture, still update wrapped textures + if (!shaders_enabled || surface_texture || wrap_texture) { - finalheight = texheight; - finalwidth = texwidth; + m_texture_manager->compute_texture_size(finalwidth, finalheight, &finalwidth, &finalheight); - m_xborderpix = 0; - m_yborderpix = 0; + // if we added pixels for the border, and that just barely pushed us over, take it back + if (finalwidth > m_texture_manager->get_max_texture_width() || finalheight > m_texture_manager->get_max_texture_height()) + { + finalheight = texheight; + finalwidth = texwidth; + + m_xborderpix = 0; + m_yborderpix = 0; - compute_size_subroutine(finalwidth, finalheight, &finalwidth, &finalheight); + m_texture_manager->compute_texture_size(finalwidth, finalheight, &finalwidth, &finalheight); + } } // if we're above the max width/height, do what? @@ -2714,18 +2747,20 @@ cache_target::~cache_target() // cache_target::init - initializes a target cache //============================================================ -bool cache_target::init(renderer_d3d9 *d3d, d3d_base *d3dintf, int width, int height, int prescale_x, int prescale_y) +bool cache_target::init(renderer_d3d9 *d3d, d3d_base *d3dintf, int target_width, int target_height) { - HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &last_texture); + // d3d->get_texture_manager()->compute_texture_size(target_width, target_height, &target_width, &target_height); + + this->target_width = target_width; + this->target_height = target_height; + + HRESULT result = (*d3dintf->device.create_texture)(d3d->get_device(), target_width, target_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &last_texture); if (result != D3D_OK) { return false; } (*d3dintf->texture.get_surface_level)(last_texture, 0, &last_target); - target_width = width * prescale_x; - target_height = height * prescale_y; - return true; } @@ -2743,34 +2778,34 @@ d3d_render_target::~d3d_render_target() (*d3dintf->texture.release)(bloom_texture[index]); bloom_texture[index] = nullptr; } - if (bloom_target[index] != nullptr) + if (bloom_surface[index] != nullptr) { - (*d3dintf->surface.release)(bloom_target[index]); - bloom_target[index] = nullptr; + (*d3dintf->surface.release)(bloom_surface[index]); + bloom_surface[index] = nullptr; } } for (int index = 0; index < 2; index++) { - if (native_texture[index] != nullptr) + if (source_texture[index] != nullptr) { - (*d3dintf->texture.release)(native_texture[index]); - native_texture[index] = nullptr; + (*d3dintf->texture.release)(source_texture[index]); + source_texture[index] = nullptr; } - if (native_target[index] != nullptr) + if (source_surface[index] != nullptr) { - (*d3dintf->surface.release)(native_target[index]); - native_target[index] = nullptr; + (*d3dintf->surface.release)(source_surface[index]); + source_surface[index] = nullptr; } - if (prescale_texture[index] != nullptr) + if (target_texture[index] != nullptr) { - (*d3dintf->texture.release)(prescale_texture[index]); - prescale_texture[index] = nullptr; + (*d3dintf->texture.release)(target_texture[index]); + target_texture[index] = nullptr; } - if (prescale_target[index] != nullptr) + if (target_surface[index] != nullptr) { - (*d3dintf->surface.release)(prescale_target[index]); - prescale_target[index] = nullptr; + (*d3dintf->surface.release)(target_surface[index]); + target_surface[index] = nullptr; } } } @@ -2780,51 +2815,63 @@ d3d_render_target::~d3d_render_target() // d3d_render_target::init - initializes a render target //============================================================ -bool d3d_render_target::init(renderer_d3d9 *d3d, d3d_base *d3dintf, int width, int height, int prescale_x, int prescale_y) +bool d3d_render_target::init(renderer_d3d9 *d3d, d3d_base *d3dintf, int width, int height, int target_width, int target_height) { HRESULT result; + // d3d->get_texture_manager()->compute_texture_size(target_width, target_height, &target_width, &target_height); + + this->width = width; + this->height = height; + + this->target_width = target_width; + this->target_height = target_height; + for (int index = 0; index < 2; index++) { - result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &native_texture[index]); + result = (*d3dintf->device.create_texture)(d3d->get_device(), width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &source_texture[index]); if (result != D3D_OK) { return false; } - (*d3dintf->texture.get_surface_level)(native_texture[index], 0, &native_target[index]); + (*d3dintf->texture.get_surface_level)(source_texture[index], 0, &source_surface[index]); - result = (*d3dintf->device.create_texture)(d3d->get_device(), width * prescale_x, height * prescale_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &prescale_texture[index]); + result = (*d3dintf->device.create_texture)(d3d->get_device(), target_width, target_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &target_texture[index]); if (result != D3D_OK) { return false; } - (*d3dintf->texture.get_surface_level)(prescale_texture[index], 0, &prescale_target[index]); + (*d3dintf->texture.get_surface_level)(target_texture[index], 0, &target_surface[index]); } - int bloom_index = 0; - float bloom_size = (d3d->get_width() < d3d->get_height()) ? d3d->get_width() : d3d->get_height(); - float bloom_width = d3d->get_width(); - float bloom_height = d3d->get_height(); - for (; bloom_size >= 2.0f && bloom_index < 11; bloom_size *= 0.5f) + bool vector_screen = + d3d->window().machine().first_screen()->screen_type() == SCREEN_TYPE_VECTOR; + + // larger blur width for vector screens than raster screens + float scale_factor = vector_screen ? 0.5f : 0.75f; + + float bloom_width = (float)width; + float bloom_height = (float)height; + float bloom_size = bloom_width < bloom_height ? bloom_width : bloom_height; + for (int bloom_index = 0; bloom_index < 11 && bloom_size >= 2.0f; bloom_size *= scale_factor) { - bloom_width *= 0.5f; - bloom_height *= 0.5f; + this->bloom_dims[bloom_index][0] = (int)bloom_width; + this->bloom_dims[bloom_index][1] = (int)bloom_height; result = (*d3dintf->device.create_texture)(d3d->get_device(), (int)bloom_width, (int)bloom_height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bloom_texture[bloom_index]); if (result != D3D_OK) { return false; } - (*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_target[bloom_index]); + (*d3dintf->texture.get_surface_level)(bloom_texture[bloom_index], 0, &bloom_surface[bloom_index]); - bloom_index++; - } + bloom_width *= scale_factor; + bloom_height *= scale_factor; - this->width = width; - this->height = height; + bloom_index++; - target_width = width * prescale_x; - target_height = height * prescale_y; + this->bloom_count = bloom_index; + } return true; } |