]> git.sesse.net Git - nageru/commitdiff
Small refactoring in PBOFrameAllocator.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 20 Apr 2018 20:30:38 +0000 (22:30 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 20 Apr 2018 20:30:38 +0000 (22:30 +0200)
pbo_frame_allocator.cpp
pbo_frame_allocator.h

index bdd9beb8f0a034c6ba777178e916697a78e7d0d6..ea17f1259fde4076320c9ebdb37da6c714a6c5f3 100644 (file)
@@ -31,171 +31,176 @@ PBOFrameAllocator::PBOFrameAllocator(bmusb::PixelFormat pixel_format, size_t fra
 {
        userdata.reset(new Userdata[num_queued_frames]);
        for (size_t i = 0; i < num_queued_frames; ++i) {
-               GLuint pbo;
-               glGenBuffers(1, &pbo);
+               init_frame(i, frame_size, width, height, permissions, map_bits);
+       }
+       glBindBuffer(buffer, 0);
+       check_error();
+       glBindTexture(GL_TEXTURE_2D, 0);
+       check_error();
+}
+
+void PBOFrameAllocator::init_frame(size_t frame_idx, size_t frame_size, GLuint width, GLuint height, GLenum permissions, GLenum map_bits)
+{
+       GLuint pbo;
+       glGenBuffers(1, &pbo);
+       check_error();
+       glBindBuffer(buffer, pbo);
+       check_error();
+       glBufferStorage(buffer, frame_size, nullptr, permissions | GL_MAP_PERSISTENT_BIT);
+       check_error();
+
+       Frame frame;
+       frame.data = (uint8_t *)glMapBufferRange(buffer, 0, frame_size, permissions | map_bits | GL_MAP_PERSISTENT_BIT);
+       frame.data2 = frame.data + frame_size / 2;
+       check_error();
+       frame.size = frame_size;
+       frame.userdata = &userdata[frame_idx];
+       userdata[frame_idx].pbo = pbo;
+       userdata[frame_idx].pixel_format = pixel_format;
+       frame.owner = this;
+
+       // For 8-bit non-planar Y'CbCr, we ask the driver to split Y' and Cb/Cr
+       // into separate textures. For 10-bit, the input format (v210)
+       // is complicated enough that we need to interpolate up to 4:4:4,
+       // which we do in a compute shader ourselves. For BGRA, the data
+       // is already 4:4:4:4.
+       frame.interleaved = (pixel_format == bmusb::PixelFormat_8BitYCbCr);
+
+       // Create textures. We don't allocate any data for the second field at this point
+       // (just create the texture state with the samplers), since our default assumed
+       // resolution is progressive.
+       switch (pixel_format) {
+       case bmusb::PixelFormat_8BitYCbCr:
+               glGenTextures(2, userdata[frame_idx].tex_y);
                check_error();
-               glBindBuffer(buffer, pbo);
+               glGenTextures(2, userdata[frame_idx].tex_cbcr);
                check_error();
-               glBufferStorage(buffer, frame_size, nullptr, permissions | GL_MAP_PERSISTENT_BIT);
+               break;
+       case bmusb::PixelFormat_10BitYCbCr:
+               glGenTextures(2, userdata[frame_idx].tex_v210);
                check_error();
-
-               Frame frame;
-               frame.data = (uint8_t *)glMapBufferRange(buffer, 0, frame_size, permissions | map_bits | GL_MAP_PERSISTENT_BIT);
-               frame.data2 = frame.data + frame_size / 2;
+               glGenTextures(2, userdata[frame_idx].tex_444);
+               check_error();
+               break;
+       case bmusb::PixelFormat_8BitBGRA:
+               glGenTextures(2, userdata[frame_idx].tex_rgba);
+               check_error();
+               break;
+       case bmusb::PixelFormat_8BitYCbCrPlanar:
+               glGenTextures(2, userdata[frame_idx].tex_y);
                check_error();
-               frame.size = frame_size;
-               frame.userdata = &userdata[i];
-               userdata[i].pbo = pbo;
-               userdata[i].pixel_format = pixel_format;
-               frame.owner = this;
+               glGenTextures(2, userdata[frame_idx].tex_cb);
+               check_error();
+               glGenTextures(2, userdata[frame_idx].tex_cr);
+               check_error();
+               break;
+       default:
+               assert(false);
+       }
 
-               // For 8-bit non-planar Y'CbCr, we ask the driver to split Y' and Cb/Cr
-               // into separate textures. For 10-bit, the input format (v210)
-               // is complicated enough that we need to interpolate up to 4:4:4,
-               // which we do in a compute shader ourselves. For BGRA, the data
-               // is already 4:4:4:4.
-               frame.interleaved = (pixel_format == bmusb::PixelFormat_8BitYCbCr);
+       userdata[frame_idx].last_width[0] = width;
+       userdata[frame_idx].last_height[0] = height;
+       userdata[frame_idx].last_cbcr_width[0] = width / 2;
+       userdata[frame_idx].last_cbcr_height[0] = height;
+       userdata[frame_idx].last_v210_width[0] = 0;
 
-               // Create textures. We don't allocate any data for the second field at this point
-               // (just create the texture state with the samplers), since our default assumed
-               // resolution is progressive.
+       userdata[frame_idx].last_width[1] = 0;
+       userdata[frame_idx].last_height[1] = 0;
+       userdata[frame_idx].last_cbcr_width[1] = 0;
+       userdata[frame_idx].last_cbcr_height[1] = 0;
+       userdata[frame_idx].last_v210_width[1] = 0;
+
+       userdata[frame_idx].last_interlaced = false;
+       userdata[frame_idx].last_has_signal = false;
+       userdata[frame_idx].last_is_connected = false;
+       for (unsigned field = 0; field < 2; ++field) {
                switch (pixel_format) {
-               case bmusb::PixelFormat_8BitYCbCr:
-                       glGenTextures(2, userdata[i].tex_y);
+               case bmusb::PixelFormat_10BitYCbCr: {
+                       const size_t v210_width = v210Converter::get_minimum_v210_texture_width(width);
+
+                       // Seemingly we need to set the minification filter even though
+                       // shader image loads don't use them, or NVIDIA will just give us
+                       // zero back.
+                       glBindTexture(GL_TEXTURE_2D, userdata[frame_idx].tex_v210[field]);
                        check_error();
-                       glGenTextures(2, userdata[i].tex_cbcr);
+                       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+                       check_error();
+                       if (field == 0) {
+                               userdata[frame_idx].last_v210_width[0] = v210_width;
+                               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, v210_width, height, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, nullptr);
+                               check_error();
+                       }
+
+                       glBindTexture(GL_TEXTURE_2D, userdata[frame_idx].tex_444[field]);
                        check_error();
+                       set_clamp_to_edge();
+                       if (field == 0) {
+                               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, width, height, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, nullptr);
+                               check_error();
+                       }
                        break;
-               case bmusb::PixelFormat_10BitYCbCr:
-                       glGenTextures(2, userdata[i].tex_v210);
+               }
+               case bmusb::PixelFormat_8BitYCbCr:
+                       glBindTexture(GL_TEXTURE_2D, userdata[frame_idx].tex_y[field]);
                        check_error();
-                       glGenTextures(2, userdata[i].tex_444);
+                       set_clamp_to_edge();
+                       if (field == 0) {
+                               glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
+                               check_error();
+                       }
+
+                       glBindTexture(GL_TEXTURE_2D, userdata[frame_idx].tex_cbcr[field]);
                        check_error();
+                       set_clamp_to_edge();
+                       if (field == 0) {
+                               glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, width / 2, height, 0, GL_RG, GL_UNSIGNED_BYTE, nullptr);
+                               check_error();
+                       }
                        break;
                case bmusb::PixelFormat_8BitBGRA:
-                       glGenTextures(2, userdata[i].tex_rgba);
+                       glBindTexture(GL_TEXTURE_2D, userdata[frame_idx].tex_rgba[field]);
                        check_error();
+                       set_clamp_to_edge();
+                       if (field == 0) {
+                               if (global_flags.can_disable_srgb_decoder) {  // See the comments in tweaked_inputs.h.
+                                       glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
+                               } else {
+                                       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
+                               }
+                               check_error();
+                       }
                        break;
                case bmusb::PixelFormat_8BitYCbCrPlanar:
-                       glGenTextures(2, userdata[i].tex_y);
-                       check_error();
-                       glGenTextures(2, userdata[i].tex_cb);
+                       glBindTexture(GL_TEXTURE_2D, userdata[frame_idx].tex_y[field]);
                        check_error();
-                       glGenTextures(2, userdata[i].tex_cr);
-                       check_error();
-                       break;
-               default:
-                       assert(false);
-               }
-
-               userdata[i].last_width[0] = width;
-               userdata[i].last_height[0] = height;
-               userdata[i].last_cbcr_width[0] = width / 2;
-               userdata[i].last_cbcr_height[0] = height;
-               userdata[i].last_v210_width[0] = 0;
-
-               userdata[i].last_width[1] = 0;
-               userdata[i].last_height[1] = 0;
-               userdata[i].last_cbcr_width[1] = 0;
-               userdata[i].last_cbcr_height[1] = 0;
-               userdata[i].last_v210_width[1] = 0;
-
-               userdata[i].last_interlaced = false;
-               userdata[i].last_has_signal = false;
-               userdata[i].last_is_connected = false;
-               for (unsigned field = 0; field < 2; ++field) {
-                       switch (pixel_format) {
-                       case bmusb::PixelFormat_10BitYCbCr: {
-                               const size_t v210_width = v210Converter::get_minimum_v210_texture_width(width);
-
-                               // Seemingly we need to set the minification filter even though
-                               // shader image loads don't use them, or NVIDIA will just give us
-                               // zero back.
-                               glBindTexture(GL_TEXTURE_2D, userdata[i].tex_v210[field]);
+                       set_clamp_to_edge();
+                       if (field == 0) {
+                               glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
                                check_error();
-                               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-                               check_error();
-                               if (field == 0) {
-                                       userdata[i].last_v210_width[0] = v210_width;
-                                       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, v210_width, height, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, nullptr);
-                                       check_error();
-                               }
-
-                               glBindTexture(GL_TEXTURE_2D, userdata[i].tex_444[field]);
-                               check_error();
-                               set_clamp_to_edge();
-                               if (field == 0) {
-                                       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB10_A2, width, height, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, nullptr);
-                                       check_error();
-                               }
-                               break;
                        }
-                       case bmusb::PixelFormat_8BitYCbCr:
-                               glBindTexture(GL_TEXTURE_2D, userdata[i].tex_y[field]);
-                               check_error();
-                               set_clamp_to_edge();
-                               if (field == 0) {
-                                       glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
-                                       check_error();
-                               }
-
-                               glBindTexture(GL_TEXTURE_2D, userdata[i].tex_cbcr[field]);
-                               check_error();
-                               set_clamp_to_edge();
-                               if (field == 0) {
-                                       glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, width / 2, height, 0, GL_RG, GL_UNSIGNED_BYTE, nullptr);
-                                       check_error();
-                               }
-                               break;
-                       case bmusb::PixelFormat_8BitBGRA:
-                               glBindTexture(GL_TEXTURE_2D, userdata[i].tex_rgba[field]);
-                               check_error();
-                               set_clamp_to_edge();
-                               if (field == 0) {
-                                       if (global_flags.can_disable_srgb_decoder) {  // See the comments in tweaked_inputs.h.
-                                               glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
-                                       } else {
-                                               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, nullptr);
-                                       }
-                                       check_error();
-                               }
-                               break;
-                       case bmusb::PixelFormat_8BitYCbCrPlanar:
-                               glBindTexture(GL_TEXTURE_2D, userdata[i].tex_y[field]);
-                               check_error();
-                               set_clamp_to_edge();
-                               if (field == 0) {
-                                       glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
-                                       check_error();
-                               }
 
-                               glBindTexture(GL_TEXTURE_2D, userdata[i].tex_cb[field]);
+                       glBindTexture(GL_TEXTURE_2D, userdata[frame_idx].tex_cb[field]);
+                       check_error();
+                       set_clamp_to_edge();
+                       if (field == 0) {
+                               glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width / 2, height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
                                check_error();
-                               set_clamp_to_edge();
-                               if (field == 0) {
-                                       glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width / 2, height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
-                                       check_error();
-                               }
+                       }
 
-                               glBindTexture(GL_TEXTURE_2D, userdata[i].tex_cr[field]);
+                       glBindTexture(GL_TEXTURE_2D, userdata[frame_idx].tex_cr[field]);
+                       check_error();
+                       set_clamp_to_edge();
+                       if (field == 0) {
+                               glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width / 2, height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
                                check_error();
-                               set_clamp_to_edge();
-                               if (field == 0) {
-                                       glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width / 2, height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
-                                       check_error();
-                               }
-                               break;
-                       default:
-                               assert(false);
                        }
+                       break;
+               default:
+                       assert(false);
                }
-
-               freelist.push(frame);
        }
-       glBindBuffer(buffer, 0);
-       check_error();
-       glBindTexture(GL_TEXTURE_2D, 0);
-       check_error();
+
+       freelist.push(frame);
 }
 
 PBOFrameAllocator::~PBOFrameAllocator()
@@ -203,43 +208,48 @@ PBOFrameAllocator::~PBOFrameAllocator()
        while (!freelist.empty()) {
                Frame frame = freelist.front();
                freelist.pop();
-               GLuint pbo = ((Userdata *)frame.userdata)->pbo;
-               glBindBuffer(buffer, pbo);
+               destroy_frame(&frame);
+       }
+}
+
+void PBOFrameAllocator::destroy_frame(Frame *frame)
+{
+       GLuint pbo = ((Userdata *)frame->userdata)->pbo;
+       glBindBuffer(buffer, pbo);
+       check_error();
+       glUnmapBuffer(buffer);
+       check_error();
+       glBindBuffer(buffer, 0);
+       check_error();
+       glDeleteBuffers(1, &pbo);
+       check_error();
+       switch (pixel_format) {
+       case bmusb::PixelFormat_10BitYCbCr:
+               glDeleteTextures(2, ((Userdata *)frame->userdata)->tex_v210);
                check_error();
-               glUnmapBuffer(buffer);
+               glDeleteTextures(2, ((Userdata *)frame->userdata)->tex_444);
                check_error();
-               glBindBuffer(buffer, 0);
+               break;
+       case bmusb::PixelFormat_8BitYCbCr:
+               glDeleteTextures(2, ((Userdata *)frame->userdata)->tex_y);
                check_error();
-               glDeleteBuffers(1, &pbo);
+               glDeleteTextures(2, ((Userdata *)frame->userdata)->tex_cbcr);
                check_error();
-               switch (pixel_format) {
-               case bmusb::PixelFormat_10BitYCbCr:
-                       glDeleteTextures(2, ((Userdata *)frame.userdata)->tex_v210);
-                       check_error();
-                       glDeleteTextures(2, ((Userdata *)frame.userdata)->tex_444);
-                       check_error();
-                       break;
-               case bmusb::PixelFormat_8BitYCbCr:
-                       glDeleteTextures(2, ((Userdata *)frame.userdata)->tex_y);
-                       check_error();
-                       glDeleteTextures(2, ((Userdata *)frame.userdata)->tex_cbcr);
-                       check_error();
-                       break;
-               case bmusb::PixelFormat_8BitBGRA:
-                       glDeleteTextures(2, ((Userdata *)frame.userdata)->tex_rgba);
-                       check_error();
-                       break;
-               case bmusb::PixelFormat_8BitYCbCrPlanar:
-                       glDeleteTextures(2, ((Userdata *)frame.userdata)->tex_y);
-                       check_error();
-                       glDeleteTextures(2, ((Userdata *)frame.userdata)->tex_cb);
-                       check_error();
-                       glDeleteTextures(2, ((Userdata *)frame.userdata)->tex_cr);
-                       check_error();
-                       break;
-               default:
-                       assert(false);
-               }
+               break;
+       case bmusb::PixelFormat_8BitBGRA:
+               glDeleteTextures(2, ((Userdata *)frame->userdata)->tex_rgba);
+               check_error();
+               break;
+       case bmusb::PixelFormat_8BitYCbCrPlanar:
+               glDeleteTextures(2, ((Userdata *)frame->userdata)->tex_y);
+               check_error();
+               glDeleteTextures(2, ((Userdata *)frame->userdata)->tex_cb);
+               check_error();
+               glDeleteTextures(2, ((Userdata *)frame->userdata)->tex_cr);
+               check_error();
+               break;
+       default:
+               assert(false);
        }
 }
 //static int sumsum = 0;
index 37fd383c3ae6aa8a32c25e03cfa8197d3d5c468e..eead7f4a32f979c8203a184f535862c6f1dab0e2 100644 (file)
@@ -55,6 +55,9 @@ public:
        };
 
 private:
+       void init_frame(size_t frame_idx, size_t frame_size, GLuint width, GLuint height, GLenum permissions, GLenum map_bits);
+       void destroy_frame(Frame *frame);
+
        bmusb::PixelFormat pixel_format;
        std::mutex freelist_mutex;
        std::queue<Frame> freelist;