Merge "drm_hwcomposer: Disable planes on frame failure" into mnc-dr-dev
diff --git a/autogl.h b/autogl.h
index 5eeca85..fc77fb0 100644
--- a/autogl.h
+++ b/autogl.h
@@ -52,8 +52,7 @@
AUTO_GL_TYPE(AutoGLProgram, GLint, 0, glDeleteProgram(p))
struct AutoEGLDisplayImage {
- AutoEGLDisplayImage() : display_(EGL_NO_DISPLAY), image_(EGL_NO_IMAGE_KHR) {
- }
+ AutoEGLDisplayImage() = default;
AutoEGLDisplayImage(EGLDisplay display, EGLImageKHR image)
: display_(display), image_(image) {
@@ -98,8 +97,8 @@
}
private:
- EGLDisplay display_;
- EGLImageKHR image_;
+ EGLDisplay display_ = EGL_NO_DISPLAY;
+ EGLImageKHR image_ = EGL_NO_IMAGE_KHR;
};
struct AutoEGLImageAndGLTexture {
diff --git a/drm_hwcomposer.h b/drm_hwcomposer.h
index fdf389b..1490438 100644
--- a/drm_hwcomposer.h
+++ b/drm_hwcomposer.h
@@ -175,7 +175,7 @@
return importer_ != NULL;
}
- hwc_drm_bo *operator->();
+ const hwc_drm_bo *operator->() const;
void Clear();
@@ -257,11 +257,12 @@
UniqueFd acquire_fence;
OutputFd release_fence;
- DrmHwcLayer() = default;
- DrmHwcLayer(DrmHwcLayer &&rhs) = default;
-
int InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
const gralloc_module_t *gralloc);
+
+ buffer_handle_t get_usable_handle() const {
+ return handle.get() != NULL ? handle.get() : sf_handle;
+ }
};
struct DrmHwcDisplayContents {
diff --git a/drmcomposition.cpp b/drmcomposition.cpp
index 55fa00c..4b293ee 100644
--- a/drmcomposition.cpp
+++ b/drmcomposition.cpp
@@ -58,10 +58,9 @@
// If the display hasn't been modeset yet, this will be NULL
DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
- int ret = composition_map_[(*iter)->display()]->Init(drm_, crtc, importer_,
- frame_no);
+ int ret = composition_map_[display]->Init(drm_, crtc, importer_, frame_no);
if (ret) {
- ALOGE("Failed to init display composition for %d", (*iter)->display());
+ ALOGE("Failed to init display composition for %d", display);
return ret;
}
}
diff --git a/drmcompositor.cpp b/drmcompositor.cpp
index ad4cf88..b486d7b 100644
--- a/drmcompositor.cpp
+++ b/drmcompositor.cpp
@@ -76,7 +76,7 @@
int ret = compositor_map_[display].QueueComposition(
composition->TakeDisplayComposition(display));
if (ret) {
- ALOGE("Failed to queue composition for display %d", display);
+ ALOGE("Failed to queue composition for display %d (%d)", display, ret);
return ret;
}
}
diff --git a/glworker.cpp b/glworker.cpp
index ffb4182..162005c 100644
--- a/glworker.cpp
+++ b/glworker.cpp
@@ -176,54 +176,73 @@
return shader;
}
+static std::string GenerateVertexShader(int layer_count) {
+ std::ostringstream vertex_shader_stream;
+ vertex_shader_stream
+ << "#version 300 es\n"
+ << "#define LAYER_COUNT " << layer_count << "\n"
+ << "precision mediump int;\n"
+ << "uniform vec4 uViewport;\n"
+ << "uniform vec4 uLayerCrop[LAYER_COUNT];\n"
+ << "uniform mat2 uTexMatrix[LAYER_COUNT];\n"
+ << "in vec2 vPosition;\n"
+ << "in vec2 vTexCoords;\n"
+ << "out vec2 fTexCoords[LAYER_COUNT];\n"
+ << "void main() {\n"
+ << " for (int i = 0; i < LAYER_COUNT; i++) {\n"
+ << " vec2 tempCoords = vTexCoords * uTexMatrix[i];\n"
+ << " fTexCoords[i] =\n"
+ << " uLayerCrop[i].xy + tempCoords * uLayerCrop[i].zw;\n"
+ << " }\n"
+ << " vec2 scaledPosition = uViewport.xy + vPosition * uViewport.zw;\n"
+ << " gl_Position =\n"
+ << " vec4(scaledPosition * vec2(2.0) - vec2(1.0), 0.0, 1.0);\n"
+ << "}\n";
+ return vertex_shader_stream.str();
+}
+
+static std::string GenerateFragmentShader(int layer_count) {
+ std::ostringstream fragment_shader_stream;
+ fragment_shader_stream << "#version 300 es\n"
+ << "#define LAYER_COUNT " << layer_count << "\n"
+ << "#extension GL_OES_EGL_image_external : require\n"
+ << "precision mediump float;\n";
+ for (int i = 0; i < layer_count; ++i) {
+ fragment_shader_stream << "uniform samplerExternalOES uLayerTexture" << i
+ << ";\n";
+ }
+ fragment_shader_stream << "uniform float uLayerAlpha[LAYER_COUNT];\n"
+ << "uniform float uLayerPremult[LAYER_COUNT];\n"
+ << "in vec2 fTexCoords[LAYER_COUNT];\n"
+ << "out vec4 oFragColor;\n"
+ << "void main() {\n"
+ << " vec3 color = vec3(0.0, 0.0, 0.0);\n"
+ << " float alphaCover = 1.0;\n"
+ << " vec4 texSample;\n"
+ << " vec3 multRgb;\n";
+ for (int i = 0; i < layer_count; ++i) {
+ if (i > 0)
+ fragment_shader_stream << " if (alphaCover > 0.5/255.0) {\n";
+ // clang-format off
+ fragment_shader_stream
+ << " texSample = texture2D(uLayerTexture" << i << ",\n"
+ << " fTexCoords[" << i << "]);\n"
+ << " multRgb = texSample.rgb *\n"
+ << " max(texSample.a, uLayerPremult[" << i << "]);\n"
+ << " color += multRgb * uLayerAlpha[" << i << "] * alphaCover;\n"
+ << " alphaCover *= 1.0 - texSample.a * uLayerAlpha[" << i << "];\n";
+ // clang-format on
+ }
+ for (int i = 0; i < layer_count - 1; ++i)
+ fragment_shader_stream << " }\n";
+ fragment_shader_stream << " oFragColor = vec4(color, 1.0 - alphaCover);\n"
+ << "}\n";
+ return fragment_shader_stream.str();
+}
+
static int GenerateShaders(std::vector<AutoGLProgram> *blend_programs) {
// Limits: GL_MAX_VARYING_COMPONENTS, GL_MAX_TEXTURE_IMAGE_UNITS,
// GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
- // clang-format off
- const GLchar *shader_preamble = "#version 300 es\n#define LAYER_COUNT ";
-
- const GLchar *vertex_shader_source =
-"\n"
-"precision mediump int; \n"
-"uniform vec4 uViewport; \n"
-"uniform vec4 uLayerCrop[LAYER_COUNT]; \n"
-"uniform mat2 uTexMatrix[LAYER_COUNT]; \n"
-"in vec2 vPosition; \n"
-"in vec2 vTexCoords; \n"
-"out vec2 fTexCoords[LAYER_COUNT]; \n"
-"void main() { \n"
-" for (int i = 0; i < LAYER_COUNT; i++) { \n"
-" vec2 tempCoords = vTexCoords * uTexMatrix[i]; \n"
-" fTexCoords[i] = uLayerCrop[i].xy + tempCoords * uLayerCrop[i].zw; \n"
-" } \n"
-" vec2 scaledPosition = uViewport.xy + vPosition * uViewport.zw; \n"
-" gl_Position = vec4(scaledPosition * vec2(2.0) - vec2(1.0), 0.0, 1.0); \n"
-"} \n";
-
- const GLchar *fragment_shader_source =
-"\n"
-"#extension GL_OES_EGL_image_external : require \n"
-"precision mediump float; \n"
-"uniform samplerExternalOES uLayerTextures[LAYER_COUNT]; \n"
-"uniform float uLayerAlpha[LAYER_COUNT]; \n"
-"uniform float uLayerPremult[LAYER_COUNT]; \n"
-"in vec2 fTexCoords[LAYER_COUNT]; \n"
-"out vec4 oFragColor; \n"
-"void main() { \n"
-" vec3 color = vec3(0.0, 0.0, 0.0); \n"
-" float alphaCover = 1.0; \n"
-" for (int i = 0; i < LAYER_COUNT; i++) { \n"
-" vec4 texSample = texture2D(uLayerTextures[i], fTexCoords[i]); \n"
-" float a = texSample.a * uLayerAlpha[i]; \n"
-" color += max(a, uLayerPremult[i]) * alphaCover * texSample.rgb; \n"
-" alphaCover *= 1.0 - a; \n"
-" if (alphaCover <= 0.5/255.0) \n"
-" break; \n"
-" } \n"
-" oFragColor = vec4(color, 1.0 - alphaCover); \n"
-"} \n";
- // clang-format on
-
int i, ret = 1;
GLint max_texture_images, status;
AutoGLShader vertex_shader, fragment_shader;
@@ -233,27 +252,26 @@
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_images);
for (i = 1; i <= max_texture_images; i++) {
- std::ostringstream layer_count_formatter;
- layer_count_formatter << i;
- std::string layer_count(layer_count_formatter.str());
- const GLchar *shader_sources[3] = {shader_preamble, layer_count.c_str(),
- NULL};
-
- shader_sources[2] = vertex_shader_source;
- vertex_shader = CompileAndCheckShader(GL_VERTEX_SHADER, 3, shader_sources,
- ret ? &shader_log : NULL);
+ std::string vertex_shader_string = GenerateVertexShader(i);
+ const GLchar *vertex_shader_source = vertex_shader_string.c_str();
+ vertex_shader = CompileAndCheckShader(
+ GL_VERTEX_SHADER, 1, &vertex_shader_source, ret ? &shader_log : NULL);
if (!vertex_shader.get()) {
if (ret)
- ALOGE("Failed to make vertex shader:\n%s", shader_log.c_str());
+ ALOGE("Failed to make vertex shader:\n%sshader source:\n%s",
+ shader_log.c_str(), vertex_shader_source);
break;
}
- shader_sources[2] = fragment_shader_source;
- fragment_shader = CompileAndCheckShader(
- GL_FRAGMENT_SHADER, 3, shader_sources, ret ? &shader_log : NULL);
+ std::string fragment_shader_string = GenerateFragmentShader(i);
+ const GLchar *fragment_shader_source = fragment_shader_string.c_str();
+ fragment_shader =
+ CompileAndCheckShader(GL_FRAGMENT_SHADER, 1, &fragment_shader_source,
+ ret ? &shader_log : NULL);
if (!fragment_shader.get()) {
if (ret)
- ALOGE("Failed to make fragment shader:\n%s", shader_log.c_str());
+ ALOGE("Failed to make fragment shader:\n%sshader source:\n%s",
+ shader_log.c_str(), fragment_shader_source);
break;
}
@@ -419,7 +437,8 @@
}
src.alpha = layer.alpha / 255.0f;
- src.premult = (layer.blending == DrmHwcBlending::kPreMult) ? 1.0f : 0.0f;
+ src.premult =
+ (layer.blending == DrmHwcBlending::kPreMult) ? 1.0f : 0.0f;
}
}
}
@@ -652,7 +671,6 @@
GLint program = blend_programs_[cmd.texture_count - 1].get();
glUseProgram(program);
GLint gl_viewport_loc = glGetUniformLocation(program, "uViewport");
- GLint gl_tex_loc = glGetUniformLocation(program, "uLayerTextures");
GLint gl_crop_loc = glGetUniformLocation(program, "uLayerCrop");
GLint gl_alpha_loc = glGetUniformLocation(program, "uLayerAlpha");
GLint gl_premult_loc = glGetUniformLocation(program, "uLayerPremult");
@@ -663,13 +681,18 @@
(cmd.bounds[3] - cmd.bounds[1]) / (float)frame_height);
for (unsigned src_index = 0; src_index < cmd.texture_count; src_index++) {
+ std::ostringstream texture_name_formatter;
+ texture_name_formatter << "uLayerTexture" << src_index;
+ GLint gl_tex_loc =
+ glGetUniformLocation(program, texture_name_formatter.str().c_str());
+
const RenderingCommand::TextureSource &src = cmd.textures[src_index];
glUniform1f(gl_alpha_loc + src_index, src.alpha);
glUniform1f(gl_premult_loc + src_index, src.premult);
glUniform4f(gl_crop_loc + src_index, src.crop_bounds[0],
src.crop_bounds[1], src.crop_bounds[2] - src.crop_bounds[0],
src.crop_bounds[3] - src.crop_bounds[1]);
- glUniform1i(gl_tex_loc + src_index, src_index);
+ glUniform1i(gl_tex_loc, src_index);
glUniformMatrix2fv(gl_tex_matrix_loc + src_index, 1, GL_FALSE,
src.texture_matrix);
glActiveTexture(GL_TEXTURE0 + src_index);
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index a7c9e43..6a0f4cd 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -191,9 +191,9 @@
return *this;
}
-hwc_drm_bo *DrmHwcBuffer::operator->() {
+const hwc_drm_bo *DrmHwcBuffer::operator->() const {
if (importer_ == NULL) {
- ALOGE("Access of none existent BO");
+ ALOGE("Access of non-existent BO");
exit(1);
return NULL;
}
@@ -264,16 +264,15 @@
int DrmHwcLayer::InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
const gralloc_module_t *gralloc) {
sf_handle = sf_layer->handle;
- int ret = buffer.ImportBuffer(sf_layer->handle, importer);
- if (ret)
- return ret;
-
- ret = handle.CopyBufferHandle(sf_layer->handle, gralloc);
- if (ret)
- return ret;
-
alpha = sf_layer->planeAlpha;
+ source_crop = DrmHwcRect<float>(
+ sf_layer->sourceCropf.left, sf_layer->sourceCropf.top,
+ sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom);
+ display_frame = DrmHwcRect<int>(
+ sf_layer->displayFrame.left, sf_layer->displayFrame.top,
+ sf_layer->displayFrame.right, sf_layer->displayFrame.bottom);
+
switch (sf_layer->transform) {
case 0:
transform = DrmHwcTransform::kIdentity;
@@ -313,12 +312,13 @@
return -EINVAL;
}
- source_crop = DrmHwcRect<float>(
- sf_layer->sourceCropf.left, sf_layer->sourceCropf.top,
- sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom);
- display_frame = DrmHwcRect<int>(
- sf_layer->displayFrame.left, sf_layer->displayFrame.top,
- sf_layer->displayFrame.right, sf_layer->displayFrame.bottom);
+ int ret = buffer.ImportBuffer(sf_layer->handle, importer);
+ if (ret)
+ return ret;
+
+ ret = handle.CopyBufferHandle(sf_layer->handle, gralloc);
+ if (ret)
+ return ret;
return 0;
}
@@ -501,13 +501,18 @@
layers_map.emplace_back();
DrmCompositionDisplayLayersMap &map = layers_map.back();
+ map.display = i;
std::vector<size_t> &indices_to_composite = layers_indices[i];
for (size_t j : indices_to_composite) {
hwc_layer_1_t *sf_layer = &dc->hwLayers[j];
DrmHwcLayer &layer = display_contents.layers[j];
- layer.InitFromHwcLayer(sf_layer, ctx->importer, ctx->gralloc);
+ ret = layer.InitFromHwcLayer(sf_layer, ctx->importer, ctx->gralloc);
+ if (ret) {
+ ALOGE("Failed to init composition from layer %d", ret);
+ return ret;
+ }
map.layers.emplace_back(std::move(layer));
}
}
diff --git a/seperate_rects.cpp b/seperate_rects.cpp
index bdf07bc..06fbe39 100644
--- a/seperate_rects.cpp
+++ b/seperate_rects.cpp
@@ -71,8 +71,8 @@
}
template <typename TNum, typename TId>
-void seperate_rects(const std::vector<Rect<TNum> > &in,
- std::vector<RectSet<TId, TNum> > *out) {
+void seperate_rects(const std::vector<Rect<TNum>> &in,
+ std::vector<RectSet<TId, TNum>> *out) {
// Overview:
// This algorithm is a line sweep algorithm that travels from left to right.
// The sweep stops at each vertical edge of each input rectangle in sorted
@@ -91,8 +91,8 @@
// Events are when the sweep line encounters the starting or ending edge of
// any input rectangle.
- std::set<SweepEvent<TId, TNum> > sweep_h_events; // Left or right bounds
- std::set<SweepEvent<TId, TNum> > sweep_v_events; // Top or bottom bounds
+ std::set<SweepEvent<TId, TNum>> sweep_h_events; // Left or right bounds
+ std::set<SweepEvent<TId, TNum>> sweep_v_events; // Top or bottom bounds
// A started rect is a rectangle whose left, top, bottom edge, and set of
// rectangle IDs is known. The key of this map includes all that information
@@ -102,7 +102,7 @@
// This is cleared after every event. Its declaration is here to avoid
// reallocating a vector and its buffers every event.
- std::vector<std::pair<TNum, IdSet<TId> > > active_regions;
+ std::vector<std::pair<TNum, IdSet<TId>>> active_regions;
// This pass will add rectangle start and end events to be triggered as the
// algorithm sweeps from left to right.
@@ -120,7 +120,7 @@
sweep_h_events.insert(evt);
}
- for (typename std::set<SweepEvent<TId, TNum> >::iterator it =
+ for (typename std::set<SweepEvent<TId, TNum>>::iterator it =
sweep_h_events.begin();
it != sweep_h_events.end(); ++it) {
const SweepEvent<TId, TNum> &h_evt = *it;
@@ -142,14 +142,14 @@
} else {
v_evt.type = START;
v_evt.y = rect.top;
- typename std::set<SweepEvent<TId, TNum> >::iterator start_it =
+ typename std::set<SweepEvent<TId, TNum>>::iterator start_it =
sweep_v_events.find(v_evt);
assert(start_it != sweep_v_events.end());
sweep_v_events.erase(start_it);
v_evt.type = END;
v_evt.y = rect.bottom;
- typename std::set<SweepEvent<TId, TNum> >::iterator end_it =
+ typename std::set<SweepEvent<TId, TNum>>::iterator end_it =
sweep_v_events.find(v_evt);
assert(end_it != sweep_v_events.end());
sweep_v_events.erase(end_it);
@@ -159,7 +159,7 @@
// with the current sweep line. If so, we want to continue marking up the
// sweep line before actually processing the rectangles the sweep line is
// intersecting.
- typename std::set<SweepEvent<TId, TNum> >::iterator next_it = it;
+ typename std::set<SweepEvent<TId, TNum>>::iterator next_it = it;
++next_it;
if (next_it != sweep_h_events.end()) {
if (next_it->x == h_evt.x) {
@@ -179,7 +179,7 @@
// 5), active_regions will be [({ 0 }, 3), {}, 5].
active_regions.clear();
IdSet<TId> active_set;
- for (typename std::set<SweepEvent<TId, TNum> >::iterator it =
+ for (typename std::set<SweepEvent<TId, TNum>>::iterator it =
sweep_v_events.begin();
it != sweep_v_events.end(); ++it) {
const SweepEvent<TId, TNum> &v_evt = *it;
@@ -199,7 +199,7 @@
#ifdef RECTS_DEBUG
std::cout << "x:" << h_evt.x;
- for (std::vector<std::pair<TNum, IdSet> >::iterator it =
+ for (std::vector<std::pair<TNum, IdSet>>::iterator it =
active_regions.begin();
it != active_regions.end(); ++it) {
std::cout << " " << it->first << "(" << it->second << ")"
@@ -226,7 +226,7 @@
// case, we have a new rectangle, and the already existing started rectangle
// will not be marked as seen ("true" in the std::pair) and will get ended
// by the for loop after this one. This is as intended.
- for (typename std::vector<std::pair<TNum, IdSet<TId> > >::iterator it =
+ for (typename std::vector<std::pair<TNum, IdSet<TId>>>::iterator it =
active_regions.begin();
it != active_regions.end(); ++it) {
IdSet<TId> region_set = it->second;
@@ -237,8 +237,7 @@
// An important property of active_regions is that each region where a set
// of rectangles applies is bounded at the bottom by the next (in the
// vector) region's starting y-coordinate.
- typename std::vector<std::pair<TNum, IdSet<TId> > >::iterator next_it =
- it;
+ typename std::vector<std::pair<TNum, IdSet<TId>>>::iterator next_it = it;
++next_it;
assert(next_it != active_regions.end());
@@ -300,8 +299,13 @@
}
}
-void seperate_frects_64(const std::vector<Rect<float> > &in,
- std::vector<RectSet<uint64_t, float> > *out) {
+void seperate_frects_64(const std::vector<Rect<float>> &in,
+ std::vector<RectSet<uint64_t, float>> *out) {
+ seperate_rects(in, out);
+}
+
+void seperate_rects_64(const std::vector<Rect<int>> &in,
+ std::vector<RectSet<uint64_t, int>> *out) {
seperate_rects(in, out);
}
diff --git a/seperate_rects.h b/seperate_rects.h
index 540a5e8..1e0a267 100644
--- a/seperate_rects.h
+++ b/seperate_rects.h
@@ -64,6 +64,18 @@
return true;
}
+
+ TFloat width() const {
+ return bounds[2] - bounds[0];
+ }
+
+ TFloat height() const {
+ return bounds[3] - bounds[1];
+ }
+
+ TFloat area() const {
+ return width() * height();
+ }
};
template <typename TUInt>
@@ -140,8 +152,10 @@
// rectangle indices that overlap the output rectangle encoded in a bitset. For
// example, an output rectangle that overlaps input rectangles in[0], in[1], and
// in[4], the bitset would be (ommitting leading zeroes) 10011.
-void seperate_frects_64(const std::vector<Rect<float> > &in,
- std::vector<RectSet<uint64_t, float> > *out);
+void seperate_frects_64(const std::vector<Rect<float>> &in,
+ std::vector<RectSet<uint64_t, float>> *out);
+void seperate_rects_64(const std::vector<Rect<int>> &in,
+ std::vector<RectSet<uint64_t, int>> *out);
} // namespace seperate_rects