OOP for Texture v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Mon, 04 Dec 2023 21:03:53 +0100
branchv_0
changeset 19 262828ae9682
parent 18 c4384f43c739
child 20 0899e966993e
OOP for Texture
Makefile
Shark.cpp
Texture.cpp
Texture.h
nbproject/configurations.xml
--- a/Makefile	Sun Dec 03 19:22:42 2023 +0100
+++ b/Makefile	Mon Dec 04 21:03:53 2023 +0100
@@ -30,6 +30,7 @@
     Shark.cpp \
     shader-shark.cpp \
     ImageLoader.cpp \
+    Texture.cpp \
     Shader.cpp \
     Program.cpp \
     FileMonitor.cpp
--- a/Shark.cpp	Sun Dec 03 19:22:42 2023 +0100
+++ b/Shark.cpp	Mon Dec 04 21:03:53 2023 +0100
@@ -29,6 +29,7 @@
 #include "Logger.h"
 #include "MappedFile.h"
 #include "ImageLoader.h"
+#include "Texture.h"
 #include "Shader.h"
 #include "Program.h"
 #include "FileMonitor.h"
@@ -155,18 +156,6 @@
 
 	} initialCtx, ctx;
 
-	class Texture {
-	public:
-		GLuint id;
-		std::string fileName;
-		int width;
-		int height;
-
-		GLfloat getRatio() const {
-			return (GLfloat) width / (GLfloat) height;
-		}
-	};
-
 	Display* dpy;
 	Window win;
 	XVisualInfo* vi;
@@ -177,7 +166,7 @@
 	ImageLoader imageLoader;
 	std::vector<std::shared_ptr<Shader>> shaders;
 	std::shared_ptr<Program> shaderProgram;
-	std::vector<Texture> textures;
+	std::vector<std::shared_ptr<Texture>> textures;
 
 	Configuration cfg;
 	std::ostream& logOutput = std::cerr;
@@ -192,8 +181,6 @@
 	void log(LogLevel level, std::string message);
 	int setNonBlocking(int fd);
 	void loadVertices();
-	Texture loadTexture(const std::string& fileName);
-	void updateTexture(Texture& tex, const Buffer& file);
 	bool reloadTexture(const std::string& fileName);
 	void loadTextures();
 	std::shared_ptr<Program> loadShaders();
@@ -208,11 +195,10 @@
 }
 
 Shark::~Shark() {
-	// TODO: more SBRM
+	impl->textures.clear();
 	impl->shaders.clear();
 	impl->shaderProgram = nullptr;
 	XFree(impl->vi);
-	// for (auto page : pdfTextures) glDeleteTextures(1, &page.texture);
 	glXMakeCurrent(impl->dpy, None, NULL);
 	glXDestroyContext(impl->dpy, impl->glc);
 	XDestroyWindow(impl->dpy, impl->win);
@@ -498,8 +484,8 @@
 
 void Shark::Impl::loadVertices() {
 	for (int i = 0; i < textures.size(); i++) {
-		const Texture& tex = textures[i];
-		GLfloat ratio = tex.getRatio();
+		std::shared_ptr<Texture> tex = textures[i];
+		GLfloat ratio = tex->getRatio();
 		const std::vector<GLfloat> vertices = {
 			// Vertex XYZ                      Texture XY
 			-0.80f * ratio, +0.80f, +0.0, /**/ 0.0, 0.0,
@@ -543,7 +529,7 @@
 }
 
 const std::string
-Shark::Shark::Impl::getDefaultFile(const std::string& relativePath) {
+Shark::Impl::getDefaultFile(const std::string& relativePath) {
 	const char* envName = "SHADER_SHARK_DATA_DIR";
 	const char* envValue = ::getenv(envName);
 	if (envValue) {
@@ -555,44 +541,16 @@
 	}
 }
 
-Shark::Impl::Texture Shark::Impl::loadTexture(const std::string& fileName) {
-	Texture tex;
-	tex.fileName = fileName;
-	MappedFile file(tex.fileName);
-	updateTexture(tex, file);
-	return tex;
-}
-
-void Shark::Impl::updateTexture(Texture& tex, const Buffer& file) {
-	std::shared_ptr<ImageLoader::ImageBuffer> img(imageLoader.loadImage(file));
-
-	tex.width = img->width;
-	tex.height = img->height;
-
-	glGenTextures(1, &tex.id);
-	glBindTexture(GL_TEXTURE_2D, tex.id);
-	auto GLT2D = GL_TEXTURE_2D;
-	glTexImage2D(GLT2D, 0, GL_RGBA,
-			tex.width, tex.height,
-			0, GL_RGBA, GL_UNSIGNED_BYTE,
-			img->getData());
-	glTexParameteri(GLT2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-	glTexParameteri(GLT2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-	glTexParameteri(GLT2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	glTexParameteri(GLT2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
-	glGenerateMipmap(GLT2D);
-	std::cerr << "loadTexture(\"" << tex.fileName.c_str() << "\", "
-			<< tex.width << ", " << tex.height << ") = " << tex.id << std::endl;
-	checkError(&std::cerr);
-}
-
 void Shark::Impl::loadTextures() {
 	// Load default texture if there is no configured:
 	if (cfg.textures.empty())
 		cfg.textures.push_back({getDefaultFile("textures/default.png")});
 
 	for (const Configuration::Texture& tex : cfg.textures) {
-		textures.push_back(loadTexture(tex.fileName));
+		std::shared_ptr<ImageLoader::ImageBuffer>
+				img(imageLoader.loadImage(MappedFile(tex.fileName)));
+		textures.push_back(std::make_shared<Texture>(
+				img->width, img->height, *img, tex.fileName));
 		watchedFiles.push_back(fileMonitor.watch(tex.fileName));
 		// TODO: review texture loading and binding
 		// works even without this - default texture
@@ -602,9 +560,11 @@
 }
 
 bool Shark::Impl::reloadTexture(const std::string& fileName) {
-	for (Texture& tex : textures) {
-		if (tex.fileName == fileName) {
-			updateTexture(tex, MappedFile(fileName));
+	for (std::shared_ptr<Texture> tex : textures) {
+		if (tex->getFileName() == fileName) {
+			std::shared_ptr<ImageLoader::ImageBuffer>
+					img(imageLoader.loadImage(MappedFile(fileName)));
+			tex->update(img->width, img->height, *img);
 			loadVertices();
 			return true;
 		}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Texture.cpp	Mon Dec 04 21:03:53 2023 +0100
@@ -0,0 +1,86 @@
+/**
+ * ShaderShark
+ * Copyright © 2023 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string>
+#include <stdexcept>
+
+#include "opengl.h"
+#include "Texture.h"
+
+class Texture::Impl {
+public:
+	GLuint id;
+	std::string fileName;
+	int width;
+	int height;
+};
+
+Texture::Texture(
+		int width,
+		int height,
+		const Buffer& img,
+		const std::string& fileName) : impl(new Impl()) {
+	impl->fileName = fileName;
+	glGenTextures(1, &impl->id);
+	update(width, height, img);
+}
+
+Texture::~Texture() {
+	glDeleteTextures(1, &impl->id);
+	delete impl;
+}
+
+GLuint Texture::getId() const {
+	return impl->id;
+}
+
+const std::string Texture::getFileName() const {
+	return impl->fileName;
+}
+
+int Texture::getWidth() const {
+	return impl->width;
+}
+
+int Texture::getHeight() const {
+	return impl->height;
+}
+
+GLfloat Texture::getRatio() const {
+	return (GLfloat) impl->width / (GLfloat) impl->height;
+}
+
+void Texture::update(int width, int height, const Buffer& img) {
+	impl->width = width;
+	impl->height = height;
+
+	if (img.getSize() != impl->width * impl->height * 4)
+		throw std::invalid_argument("invalid image size");
+
+	glBindTexture(GL_TEXTURE_2D, impl->id);
+	auto GLT2D = GL_TEXTURE_2D;
+	glTexImage2D(GLT2D, 0, GL_RGBA,
+			impl->width, impl->height,
+			0, GL_RGBA, GL_UNSIGNED_BYTE,
+			img.getData());
+	glTexParameteri(GLT2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+	glTexParameteri(GLT2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+	glTexParameteri(GLT2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glTexParameteri(GLT2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+	glGenerateMipmap(GLT2D);
+	checkError(&std::cerr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Texture.h	Mon Dec 04 21:03:53 2023 +0100
@@ -0,0 +1,47 @@
+/**
+ * ShaderShark
+ * Copyright © 2023 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <string>
+
+#include "Buffer.h"
+
+class Texture {
+public:
+
+	/**
+	 * @param width horizontal pixel count
+	 * @param height vertical pixel count
+	 * @param img RGBA pixels, 8 bits per channel, size == width * height * 4
+	 * @param fileName not used by this class, just stored for others
+	 */
+	Texture(int width, int height, const Buffer& img,
+			const std::string& fileName);
+	virtual ~Texture();
+	GLuint getId() const;
+	const std::string getFileName() const;
+	int getWidth() const;
+	int getHeight() const;
+	GLfloat getRatio() const;
+	void update(int width, int height, const Buffer& img);
+private:
+	class Impl;
+	Impl* impl;
+	Texture(const Texture&) = delete;
+	Texture& operator=(const Texture&) = delete;
+};
--- a/nbproject/configurations.xml	Sun Dec 03 19:22:42 2023 +0100
+++ b/nbproject/configurations.xml	Mon Dec 04 21:03:53 2023 +0100
@@ -7,6 +7,7 @@
       <in>Program.cpp</in>
       <in>Shader.cpp</in>
       <in>Shark.cpp</in>
+      <in>Texture.cpp</in>
       <in>shader-shark.cpp</in>
     </df>
     <logicalFolder name="ExternalFiles"
@@ -76,6 +77,10 @@
         <ccTool flags="0">
         </ccTool>
       </item>
+      <item path="Texture.cpp" ex="false" tool="1" flavor2="0">
+        <ccTool flags="0">
+        </ccTool>
+      </item>
       <item path="shader-shark.cpp" ex="false" tool="1" flavor2="0">
         <ccTool flags="0">
         </ccTool>