diff options
Diffstat (limited to 'util/fbcompose/OpenGLTexPartitioner.cc')
-rw-r--r-- | util/fbcompose/OpenGLTexPartitioner.cc | 163 |
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 | |||
28 | using namespace FbCompositor; | ||
29 | |||
30 | |||
31 | //--- CONSTRUCTORS AND DESTRUCTORS --------------------------------------------- | ||
32 | |||
33 | // Constructor. | ||
34 | OpenGL2DTexturePartition::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. | ||
47 | OpenGL2DTexturePartition::~OpenGL2DTexturePartition() { } | ||
48 | |||
49 | |||
50 | //--- MUTATORS ----------------------------------------------------------------- | ||
51 | |||
52 | // Sets the texture's contents to the given pixmap. | ||
53 | void 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. | ||
113 | unsigned 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. | ||
123 | std::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. | ||
150 | std::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 | } | ||