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

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

Issue 2088273003: Video Color Managament (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: bugfix Created 4 years, 5 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "cc/output/color_lut_cache.h"
6
7 #include <stdint.h>
8 #include <vector>
9
10 #include "gpu/command_buffer/client/gles2_interface.h"
11 #include "third_party/qcms/src/qcms.h"
12
13 #ifndef THIS_MUST_BE_INCLUDED_AFTER_QCMS_H
14 extern "C" {
15 #include "third_party/qcms/src/chain.h"
16 };
17 #endif
18
19 // After a LUT has not been used for this many frames, we release it.
20 const uint32_t kMaxFramesUnused = 10;
21
22 ColorLUTCache::ColorLUTCache(gpu::gles2::GLES2Interface* gl)
23 : lut_cache_(0), gl_(gl) {}
24
25 ColorLUTCache::~ColorLUTCache() {
26 GLuint textures[10];
27 size_t n = 0;
28 for (const auto& cache_entry : lut_cache_) {
29 textures[n++] = cache_entry.second.first;
30 if (n == arraysize(textures)) {
31 gl_->DeleteTextures(n, textures);
32 n = 0;
33 }
34 }
35 if (n)
36 gl_->DeleteTextures(n, textures);
37 }
38
39 namespace {
40
41 // QCMS is trixy, it has a datatype called qcms_CIE_xyY, but what it expects
42 // is in fact not xyY color coordinates, it just wants the x/y values of the
43 // primaries with Y equal to 1.0.
44 qcms_CIE_xyY xyfromXY(const media::VideoColorSpace::XY& xy) {
45 qcms_CIE_xyY ret;
46 ret.x = xy.first;
47 ret.y = xy.second;
48 ret.Y = 1.0f;
49 return ret;
50 }
51
52 } // namespace
53
54 unsigned int ColorLUTCache::MakeLUT(const media::VideoColorSpace& from,
55 const gfx::ColorSpace& to,
56 int lut_samples) {
57 media::VideoColorSpace intermediate = media::VideoColorSpace::XYZ();
58 media::ColorTransform from_transform(from, intermediate,
59 media::ColorTransform::INTENT_PERCEIVED);
60
61 std::vector<media::VideoColorSpace::XY> primaries =
62 intermediate.GetPrimaries();
63 qcms_CIE_xyYTRIPLE rgb;
64 qcms_CIE_xyY w;
65 rgb.red = xyfromXY(primaries[0]);
66 rgb.green = xyfromXY(primaries[1]);
67 rgb.blue = xyfromXY(primaries[2]);
68 w = xyfromXY(primaries[3]);
69 qcms_profile* in = qcms_profile_create_rgb_with_gamma(w, rgb, 1.0f);
70
71 const std::vector<char>& icc_data = to.GetICCProfile();
72 qcms_profile* out;
73 if (icc_data.empty()) {
74 out = qcms_profile_sRGB();
75 } else {
76 out = qcms_profile_from_memory(icc_data.data(), icc_data.size());
77 }
78
79 int lut_entries = lut_samples * lut_samples * lut_samples;
80 float inverse = 1.0f / (lut_samples - 1);
81 std::vector<float> xyz_tmp(lut_entries * 3);
82 int pos = 0;
83 for (int a = 0; a < lut_samples; a++) {
84 for (int b = 0; b < lut_samples; b++) {
85 for (int c = 0; c < lut_samples; c++) {
86 media::VideoColorSpace::TriStim tmp;
87 tmp.values[0] = a * inverse;
88 tmp.values[2] = b * inverse;
89 tmp.values[1] = c * inverse;
90 from_transform.transform(&tmp, 1);
91 xyz_tmp[pos++] = fmax(0.0f, fmin(1.0f, tmp.values[0]));
92 xyz_tmp[pos++] = fmax(0.0f, fmin(1.0f, tmp.values[1]));
93 xyz_tmp[pos++] = fmax(0.0f, fmin(1.0f, tmp.values[2]));
94 }
95 }
96 }
97 qcms_chain_transform(in, out, xyz_tmp.data(), xyz_tmp.data(),
98 lut_entries * 3);
99 qcms_profile_release(in);
100 qcms_profile_release(out);
101
102 std::vector<unsigned char> lut(lut_samples * lut_samples * lut_samples * 4);
103 unsigned char* lutp = lut.data();
104 pos = 0;
105 for (int i = 0; i < lut_entries; i++) {
106 for (int channel = 0; channel < 3; channel++) {
107 int v = (int)floorf(xyz_tmp[pos++] * 255.0 + 0.5);
108 *(lutp++) = v < 0 ? 0 : v > 255 ? 255 : v;
109 }
110 *(lutp++) = 255;
111 }
112
113 unsigned int lut_texture;
114 gl_->GenTextures(1, &lut_texture);
115 gl_->BindTexture(GL_TEXTURE_2D, lut_texture);
116 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
117 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
118 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
119 gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
120 gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lut_samples,
121 lut_samples * lut_samples, 0, GL_RGBA, GL_UNSIGNED_BYTE,
122 lut.data());
123 return lut_texture;
124 }
125
126 unsigned int ColorLUTCache::GetLUT(const media::VideoColorSpace& from,
127 const gfx::ColorSpace& to,
128 int lut_samples) {
129 CacheKey key(from, std::make_pair(to, lut_samples));
130 auto iter = lut_cache_.Get(key);
131 if (iter != lut_cache_.end()) {
132 iter->second.second = current_frame_;
133 return iter->second.first;
134 }
135
136 unsigned int lut = MakeLUT(from, to, lut_samples);
137 lut_cache_.Put(key, std::make_pair(lut, current_frame_));
138 return lut;
139 }
140
141 void ColorLUTCache::Swap() {
142 current_frame_++;
143 while (!lut_cache_.empty() &&
144 current_frame_ - lut_cache_.rbegin()->second.first >
145 kMaxFramesUnused) {
146 gl_->DeleteTextures(1, &lut_cache_.rbegin()->second.first);
147 lut_cache_.ShrinkToSize(lut_cache_.size() - 1);
148 }
149 }
OLDNEW
« no previous file with comments | « cc/output/color_lut_cache.h ('k') | cc/output/gl_renderer.h » ('j') | cc/output/gl_renderer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698