Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: cc/output/color_lut_cache.cc

Issue 2648043002: Create FP16 LUTs when needed (Closed)
Patch Set: mark all floats as floats (not doubles) Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/output/color_lut_cache.h ('k') | cc/output/gl_renderer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/output/color_lut_cache.h" 5 #include "cc/output/color_lut_cache.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <cmath> 8 #include <cmath>
9 #include <vector> 9 #include <vector>
10 10
11 #include "gpu/command_buffer/client/gles2_interface.h" 11 #include "gpu/command_buffer/client/gles2_interface.h"
12 #include "third_party/khronos/GLES2/gl2ext.h"
12 #include "ui/gfx/color_transform.h" 13 #include "ui/gfx/color_transform.h"
14 #include "ui/gfx/half_float.h"
13 15
14 // After a LUT has not been used for this many frames, we release it. 16 // After a LUT has not been used for this many frames, we release it.
15 const uint32_t kMaxFramesUnused = 10; 17 const uint32_t kMaxFramesUnused = 10;
16 18
17 ColorLUTCache::ColorLUTCache(gpu::gles2::GLES2Interface* gl) 19 ColorLUTCache::ColorLUTCache(gpu::gles2::GLES2Interface* gl,
18 : lut_cache_(0), gl_(gl) {} 20 bool texture_half_float_linear)
21 : lut_cache_(0),
22 gl_(gl),
23 texture_half_float_linear_(texture_half_float_linear) {}
19 24
20 ColorLUTCache::~ColorLUTCache() { 25 ColorLUTCache::~ColorLUTCache() {
21 GLuint textures[10]; 26 GLuint textures[10];
22 size_t n = 0; 27 size_t n = 0;
23 for (const auto& cache_entry : lut_cache_) { 28 for (const auto& cache_entry : lut_cache_) {
24 textures[n++] = cache_entry.second.texture; 29 textures[n++] = cache_entry.second.lut.texture;
25 if (n == arraysize(textures)) { 30 if (n == arraysize(textures)) {
26 gl_->DeleteTextures(n, textures); 31 gl_->DeleteTextures(n, textures);
27 n = 0; 32 n = 0;
28 } 33 }
29 } 34 }
30 if (n) 35 if (n)
31 gl_->DeleteTextures(n, textures); 36 gl_->DeleteTextures(n, textures);
32 } 37 }
33 38
34 namespace { 39 namespace {
35 40
36 unsigned char FloatToLUT(float f) { 41 void FloatToLUT(const float* f, gfx::HalfFloat* out, size_t num) {
37 return std::min<int>(255, std::max<int>(0, floorf(f * 255.0f + 0.5f))); 42 gfx::FloatToHalfFloat(f, out, num);
38 } 43 }
39 };
40 44
45 void FloatToLUT(float* f, unsigned char* out, size_t num) {
46 for (size_t i = 0; i < num; i++) {
47 out[i] = std::min<int>(255, std::max<int>(0, floorf(f[i] * 255.0f + 0.5f)));
48 }
49 }
50
51 } // namespace
52
53 template <typename T>
41 unsigned int ColorLUTCache::MakeLUT(const gfx::ColorSpace& from, 54 unsigned int ColorLUTCache::MakeLUT(const gfx::ColorSpace& from,
42 gfx::ColorSpace to, 55 gfx::ColorSpace to,
43 int lut_samples) { 56 int lut_samples) {
44 if (to == gfx::ColorSpace()) { 57 if (to == gfx::ColorSpace()) {
45 to = gfx::ColorSpace::CreateSRGB(); 58 to = gfx::ColorSpace::CreateSRGB();
46 } 59 }
47 std::unique_ptr<gfx::ColorTransform> transform( 60 std::unique_ptr<gfx::ColorTransform> transform(
48 gfx::ColorTransform::NewColorTransform( 61 gfx::ColorTransform::NewColorTransform(
49 from, to, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL)); 62 from, to, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL));
50 63
51 int lut_entries = lut_samples * lut_samples * lut_samples; 64 int lut_entries = lut_samples * lut_samples * lut_samples;
52 float inverse = 1.0f / (lut_samples - 1); 65 float inverse = 1.0f / (lut_samples - 1);
53 std::vector<unsigned char> lut(lut_entries * 4); 66 std::vector<T> lut(lut_entries * 4);
54 std::vector<gfx::ColorTransform::TriStim> samples(lut_samples); 67 std::vector<gfx::ColorTransform::TriStim> samples(lut_samples);
55 unsigned char* lutp = lut.data(); 68 T* lutp = lut.data();
69 float one = 1.0f;
70 T alpha;
71 FloatToLUT(&one, &alpha, 1);
56 for (int v = 0; v < lut_samples; v++) { 72 for (int v = 0; v < lut_samples; v++) {
57 for (int u = 0; u < lut_samples; u++) { 73 for (int u = 0; u < lut_samples; u++) {
58 for (int y = 0; y < lut_samples; y++) { 74 for (int y = 0; y < lut_samples; y++) {
59 samples[y].set_x(y * inverse); 75 samples[y].set_x(y * inverse);
60 samples[y].set_y(u * inverse); 76 samples[y].set_y(u * inverse);
61 samples[y].set_z(v * inverse); 77 samples[y].set_z(v * inverse);
62 } 78 }
63 transform->transform(samples.data(), samples.size()); 79 transform->transform(samples.data(), samples.size());
64 for (int y = 0; y < lut_samples; y++) { 80 T* lutp2 = lutp + lut_samples;
65 *(lutp++) = FloatToLUT(samples[y].x()); 81 FloatToLUT(reinterpret_cast<float*>(samples.data()), lutp2,
66 *(lutp++) = FloatToLUT(samples[y].y()); 82 lut_samples * 3);
67 *(lutp++) = FloatToLUT(samples[y].z()); 83 for (int i = 0; i < lut_samples; i++) {
68 *(lutp++) = 255; // alpha 84 *(lutp++) = *(lutp2++);
85 *(lutp++) = *(lutp2++);
86 *(lutp++) = *(lutp2++);
87 *(lutp++) = alpha;
69 } 88 }
70 } 89 }
71 } 90 }
72 91
73 unsigned int lut_texture; 92 unsigned int lut_texture;
74 gl_->GenTextures(1, &lut_texture); 93 gl_->GenTextures(1, &lut_texture);
75 gl_->BindTexture(GL_TEXTURE_2D, lut_texture); 94 gl_->BindTexture(GL_TEXTURE_2D, lut_texture);
76 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 95 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
77 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 96 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
78 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 97 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
79 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 98 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
80 gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lut_samples, 99 gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lut_samples,
81 lut_samples * lut_samples, 0, GL_RGBA, GL_UNSIGNED_BYTE, 100 lut_samples * lut_samples, 0, GL_RGBA,
101 sizeof(T) == 1 ? GL_UNSIGNED_BYTE : GL_HALF_FLOAT_OES,
82 lut.data()); 102 lut.data());
83 return lut_texture; 103 return lut_texture;
84 } 104 }
85 105
86 unsigned int ColorLUTCache::GetLUT(const gfx::ColorSpace& from, 106 ColorLUTCache::LUT ColorLUTCache::GetLUT(const gfx::ColorSpace& from,
87 const gfx::ColorSpace& to, 107 const gfx::ColorSpace& to) {
88 int lut_samples) { 108 CacheKey key(from, to);
89 CacheKey key(from, std::make_pair(to, lut_samples));
90 auto iter = lut_cache_.Get(key); 109 auto iter = lut_cache_.Get(key);
91 if (iter != lut_cache_.end()) { 110 if (iter != lut_cache_.end()) {
92 iter->second.last_used_frame = current_frame_; 111 iter->second.last_used_frame = current_frame_;
93 return iter->second.texture; 112 return iter->second.lut;
94 } 113 }
95 114
96 unsigned int lut = MakeLUT(from, to, lut_samples); 115 LUT lut;
116 // If input is HDR, and the output is scRGB, we're going to need
117 // to produce values outside of 0-1, so we'll need to make a half-float
118 // LUT. Also, we'll need to build a larger lut to maintain accuracy.
119 // All LUT sizes should be odd a some transforms hav a knee at 0.5.
120 if (to == gfx::ColorSpace::CreateSCRGBLinear() && from.IsHDR() &&
121 texture_half_float_linear_) {
122 lut.size = 37;
123 lut.texture = MakeLUT<uint16_t>(from, to, lut.size);
124 } else {
125 lut.size = 17;
126 lut.texture = MakeLUT<unsigned char>(from, to, lut.size);
127 }
97 lut_cache_.Put(key, CacheVal(lut, current_frame_)); 128 lut_cache_.Put(key, CacheVal(lut, current_frame_));
98 return lut; 129 return lut;
99 } 130 }
100 131
101 void ColorLUTCache::Swap() { 132 void ColorLUTCache::Swap() {
102 current_frame_++; 133 current_frame_++;
103 while (!lut_cache_.empty() && 134 while (!lut_cache_.empty() &&
104 current_frame_ - lut_cache_.rbegin()->second.last_used_frame > 135 current_frame_ - lut_cache_.rbegin()->second.last_used_frame >
105 kMaxFramesUnused) { 136 kMaxFramesUnused) {
106 gl_->DeleteTextures(1, &lut_cache_.rbegin()->second.texture); 137 gl_->DeleteTextures(1, &lut_cache_.rbegin()->second.lut.texture);
107 lut_cache_.ShrinkToSize(lut_cache_.size() - 1); 138 lut_cache_.ShrinkToSize(lut_cache_.size() - 1);
108 } 139 }
109 } 140 }
OLDNEW
« no previous file with comments | « cc/output/color_lut_cache.h ('k') | cc/output/gl_renderer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698