aboutsummaryrefslogtreecommitdiff
path: root/util/fbcompose/OpenGLTexPartitioner.cc
diff options
context:
space:
mode:
Diffstat (limited to 'util/fbcompose/OpenGLTexPartitioner.cc')
-rw-r--r--util/fbcompose/OpenGLTexPartitioner.cc163
1 files changed, 163 insertions, 0 deletions
diff --git a/util/fbcompose/OpenGLTexPartitioner.cc b/util/fbcompose/OpenGLTexPartitioner.cc
new file mode 100644
index 0000000..9ff810b
--- /dev/null
+++ b/util/fbcompose/OpenGLTexPartitioner.cc
@@ -0,0 +1,163 @@
1/** OpenGLTexPartitioner.cc file for the fluxbox compositor. */
2
3// Copyright (c) 2011 Gediminas Liktaras (gliktaras at gmail dot com)
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21// THE SOFTWARE.
22
23
24#include "OpenGLTexPartitioner.hh"
25
26#include "OpenGLScreen.hh"
27
28using namespace FbCompositor;
29
30
31//--- CONSTRUCTORS AND DESTRUCTORS ---------------------------------------------
32
33// Constructor.
34OpenGL2DTexturePartition::OpenGL2DTexturePartition(const OpenGLScreen &screen, bool swizzle_alpha_to_one) :
35 m_screen(screen) {
36
37 m_display = (Display*)(screen.display());
38 m_max_texture_size = screen.maxTextureSize();
39 m_pixmap = None;
40 m_swizzle_alpha_to_one = swizzle_alpha_to_one;
41
42 m_full_height = 0;
43 m_full_width = 0;
44}
45
46// Destructor.
47OpenGL2DTexturePartition::~OpenGL2DTexturePartition() { }
48
49
50//--- MUTATORS -----------------------------------------------------------------
51
52// Sets the texture's contents to the given pixmap.
53void OpenGL2DTexturePartition::setPixmap(Pixmap pixmap, bool manage_pixmap, int width, int height, int depth) {
54 // Handle the pixmap and its GC.
55 if (m_pixmap) {
56 XFreePixmap(m_display, m_pixmap);
57 m_pixmap = None;
58 }
59 if (manage_pixmap) {
60 m_pixmap = pixmap;
61 }
62 GC gc = XCreateGC(m_display, pixmap, 0, NULL);
63
64 // Set partition's dimensions and partition that space.
65 m_full_height = height;
66 m_full_width = width;
67
68 int unit_height, unit_width;
69 std::vector<XRectangle> space_parts = partitionSpace(0, 0, width, height, m_max_texture_size, &unit_width, &unit_height);
70 int total_units = unit_height * unit_width;
71
72 // Adjust number of stored partitions.
73 while ((size_t)(total_units) > m_partitions.size()) {
74 TexturePart partition;
75 partition.borders = 0;
76 partition.texture = new OpenGL2DTexture(m_screen, m_swizzle_alpha_to_one);
77 m_partitions.push_back(partition);
78 }
79 while ((size_t)(total_units) < m_partitions.size()) {
80 m_partitions.pop_back();
81 }
82
83 // Create texture partitions.
84 if (total_units == 1) {
85 m_partitions[0].borders = BORDER_ALL;
86 m_partitions[0].texture->setPixmap(pixmap, false, m_full_width, m_full_height, false);
87 } else {
88 for (int i = 0; i < unit_height; i++) {
89 for (int j = 0; j < unit_width; j++) {
90 int idx = i * unit_width + j;
91
92 // Create partition's pixmap.
93 Pixmap part_pixmap = XCreatePixmap(m_display, m_screen.rootWindow().window(),
94 space_parts[idx].width, space_parts[idx].height, depth);
95 XCopyArea(m_display, pixmap, part_pixmap, gc, space_parts[idx].x, space_parts[idx].y,
96 space_parts[idx].width, space_parts[idx].height, 0, 0);
97
98 // Set up the partition.
99 m_partitions[idx].borders = getBorderBitfield(unit_width, unit_height, j, i);
100 m_partitions[idx].texture->setPixmap(part_pixmap, true, space_parts[idx].width, space_parts[idx].height, false);
101 }
102 }
103 }
104
105 // Cleanup.
106 XFreeGC(m_display, gc);
107}
108
109
110//--- SUPPORTING FUNCTIONS -------------------------------------------------
111
112// Returns the border bitfield of the given partition.
113unsigned int FbCompositor::getBorderBitfield(int unit_width, int unit_height, int x, int y) {
114 unsigned int borders = 0;
115 borders |= ((y == 0) ? BORDER_NORTH : 0);
116 borders |= ((x == 0) ? BORDER_WEST : 0);
117 borders |= ((y == (unit_height - 1)) ? BORDER_SOUTH : 0);
118 borders |= ((x == (unit_width - 1)) ? BORDER_EAST : 0);
119 return borders;
120}
121
122// Space partitioning function.
123std::vector<XRectangle> FbCompositor::partitionSpace(int x, int y, int width, int height, int max_partition_size,
124 int *unit_width_return, int *unit_height_return) {
125 int unit_height = ((height - 1) / max_partition_size) + 1;
126 int unit_width = ((width - 1) / max_partition_size) + 1;
127
128 std::vector<XRectangle> partitions;
129 for (int i = 0; i < unit_height; i++) {
130 for (int j = 0; j < unit_width; j++) {
131 int part_x = x + j * max_partition_size;
132 int part_y = y + i * max_partition_size;
133 int part_height = ((i == (unit_height - 1)) ? (height % max_partition_size) : max_partition_size);
134 int part_width = ((j == (unit_width - 1)) ? (width % max_partition_size) : max_partition_size);
135
136 XRectangle part = { part_x, part_y, part_width, part_height };
137 partitions.push_back(part);
138 }
139 }
140
141 if (unit_width_return && unit_height_return) {
142 *unit_width_return = unit_width;
143 *unit_height_return = unit_height;
144 }
145
146 return partitions;
147}
148
149// Partitions space directly to buffers.
150std::vector<OpenGLBufferPtr> FbCompositor::partitionSpaceToBuffers(const OpenGLScreen &screen,
151 int x, int y, int width, int height) {
152
153 std::vector<XRectangle> space_part = partitionSpace(x, y, width, height, screen.maxTextureSize());
154 std::vector<OpenGLBufferPtr> buffers;
155
156 for (size_t i = 0; i < space_part.size(); i++) {
157 OpenGLBufferPtr buffer(new OpenGLBuffer(screen, GL_ARRAY_BUFFER));
158 buffer->bufferPosRectangle(screen.rootWindow().width(), screen.rootWindow().height(), space_part[i]);
159 buffers.push_back(buffer);
160 }
161
162 return buffers;
163}