summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/AbstractTexture.cpp
blob: 7e4f493601cab90b52014372ef5dcec241fcbd1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include <algorithm>

#include "Common/Assert.h"

#include "VideoCommon/AbstractTexture.h"
#include "VideoCommon/ImageWrite.h"

AbstractTexture::AbstractTexture(const TextureConfig& c) : m_config(c)
{
}

AbstractTexture::~AbstractTexture() = default;

bool AbstractTexture::Save(const std::string& filename, unsigned int level)
{
  // We can't dump compressed textures currently (it would mean drawing them to a RGBA8
  // framebuffer, and saving that). TextureCache does not call Save for custom textures
  // anyway, so this is fine for now.
  _assert_(m_config.format == AbstractTextureFormat::RGBA8);

  auto result = level == 0 ? Map() : Map(level);

  if (!result.has_value())
  {
    return false;
  }

  auto raw_data = result.value();
  return TextureToPng(raw_data.data, raw_data.stride, filename, raw_data.width, raw_data.height);
}

std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::Map()
{
  if (m_currently_mapped)
  {
    Unmap();
    m_currently_mapped = false;
  }
  auto result = MapFullImpl();

  if (!result.has_value())
  {
    m_currently_mapped = false;
    return {};
  }

  m_currently_mapped = true;
  return result;
}

std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::Map(u32 level, u32 x, u32 y,
                                                                    u32 width, u32 height)
{
  _assert_(level < m_config.levels);

  u32 max_level_width = std::max(m_config.width >> level, 1u);
  u32 max_level_height = std::max(m_config.height >> level, 1u);

  _assert_(width < max_level_width);
  _assert_(height < max_level_height);

  auto result = MapRegionImpl(level, x, y, width, height);

  if (!result.has_value())
  {
    m_currently_mapped = false;
    return {};
  }

  m_currently_mapped = true;
  return result;
}

std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::Map(u32 level)
{
  _assert_(level < m_config.levels);

  u32 level_width = std::max(m_config.width >> level, 1u);
  u32 level_height = std::max(m_config.height >> level, 1u);

  return Map(level, 0, 0, level_width, level_height);
}

void AbstractTexture::Unmap()
{
}

std::optional<AbstractTexture::RawTextureInfo> AbstractTexture::MapFullImpl()
{
  return {};
}

std::optional<AbstractTexture::RawTextureInfo>
AbstractTexture::MapRegionImpl(u32 level, u32 x, u32 y, u32 width, u32 height)
{
  return {};
}

bool AbstractTexture::IsCompressedHostTextureFormat(AbstractTextureFormat format)
{
  // This will need to be changed if we add any other uncompressed formats.
  return format != AbstractTextureFormat::RGBA8;
}

size_t AbstractTexture::CalculateHostTextureLevelPitch(AbstractTextureFormat format, u32 row_length)
{
  switch (format)
  {
  case AbstractTextureFormat::DXT1:
    return static_cast<size_t>(std::max(1u, row_length / 4)) * 8;
  case AbstractTextureFormat::DXT3:
  case AbstractTextureFormat::DXT5:
  case AbstractTextureFormat::BPTC:
    return static_cast<size_t>(std::max(1u, row_length / 4)) * 16;
  case AbstractTextureFormat::RGBA8:
  default:
    return static_cast<size_t>(row_length) * 4;
  }
}

const TextureConfig& AbstractTexture::GetConfig() const
{
  return m_config;
}