dolphin/Source/Core/VideoCommon/VertexManagerBase.h
Michael Maltese d10d09ccc1 VideoCommon: rework anamorphic widescreen heuristic
Some widescreen hacks (see below) properly force anamorphic output, but
don't make the last projection in a frame 16:9, so Dolphin doesn't
display it correctly.

This changes the heuristic code to assume a frame is anamorphic based on
the total number of vertex flushes in 4:3 and 16:9 projections that
frame. It also adds a bit of "aspect ratio inertia" by making it harder
to switch aspect ratios, which takes care of aspect ratio flickering
that some games / widescreen hacks would be susceptible with the new
logic.

I've tested this on SSX Tricky's native anamorphic support, Tom Clancy's
Splinter Cell (it stayed in 4:3 the whole time), and on the following
widescreen hacks for which the heuristic doesn't currently work:

Paper Mario: The Thousand-Year Door (Gecko widescreen code from Nintendont)
C202F310 00000003
3DC08042 3DE03FD8
91EEF6D8 4E800020
60000000 00000000
04199598 4E800020
C200F500 00000004
3DE08082 3DC0402B
61CE12A2 91CFA1BC
60000000 387D015C
60000000 00000000
C200F508 00000004
3DE08082 3DC04063
61CEE8D3 91CFA1BC
60000000 7FC3F378
60000000 00000000

The Simpsons: Hit & Run (AR widescreen code from the wiki)
04004600 C002A604
04004604 C09F0014
04004608 FC002040
0400460C 4082000C
04004610 C002A608
04004614 EC630032
04004618 48220508
04041A5C 38600001
04224344 C002A60C
04224B1C 4BDDFAE4
044786B0 3FAAAAAB
04479F28 3FA33333
2017-04-05 17:23:16 -07:00

96 lines
2.3 KiB
C++

// Copyright 2010 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <vector>
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h"
class DataReader;
class NativeVertexFormat;
class PointerWrap;
struct PortableVertexDeclaration;
enum PrimitiveType
{
PRIMITIVE_POINTS,
PRIMITIVE_LINES,
PRIMITIVE_TRIANGLES,
};
struct Slope
{
float dfdx;
float dfdy;
float f0;
bool dirty;
};
class VertexManagerBase
{
private:
// 3 pos
static constexpr u32 SMALLEST_POSSIBLE_VERTEX = sizeof(float) * 3;
// 3 pos, 3*3 normal, 2*u32 color, 8*4 tex, 1 posMat
static constexpr u32 LARGEST_POSSIBLE_VERTEX = sizeof(float) * 45 + sizeof(u32) * 2;
static constexpr u32 MAX_PRIMITIVES_PER_COMMAND = 65535;
public:
static constexpr u32 MAXVBUFFERSIZE =
ROUND_UP_POW2(MAX_PRIMITIVES_PER_COMMAND * LARGEST_POSSIBLE_VERTEX);
// We may convert triangle-fans to triangle-lists, almost 3x as many indices.
static constexpr u32 MAXIBUFFERSIZE = ROUND_UP_POW2(MAX_PRIMITIVES_PER_COMMAND * 3);
VertexManagerBase();
// needs to be virtual for DX11's dtor
virtual ~VertexManagerBase();
DataReader PrepareForAdditionalData(int primitive, u32 count, u32 stride, bool cullall);
void FlushData(u32 count, u32 stride);
void Flush();
virtual std::unique_ptr<NativeVertexFormat>
CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) = 0;
void DoState(PointerWrap& p);
std::pair<size_t, size_t> ResetFlushAspectRatioCount();
protected:
virtual void vDoState(PointerWrap& p) {}
PrimitiveType m_current_primitive_type = PrimitiveType::PRIMITIVE_POINTS;
virtual void ResetBuffer(u32 stride) = 0;
u8* m_cur_buffer_pointer = nullptr;
u8* m_base_buffer_pointer = nullptr;
u8* m_end_buffer_pointer = nullptr;
u32 GetRemainingSize() const;
static u32 GetRemainingIndices(int primitive);
Slope m_zslope = {};
void CalculateZSlope(NativeVertexFormat* format);
bool m_cull_all = false;
private:
bool m_is_flushed = true;
size_t m_flush_count_4_3 = 0;
size_t m_flush_count_anamorphic = 0;
virtual void vFlush() = 0;
virtual void CreateDeviceObjects() {}
virtual void DestroyDeviceObjects() {}
};
extern std::unique_ptr<VertexManagerBase> g_vertex_manager;