Rename image -> video.
[dcpomatic.git] / src / wx / gl_video_view.cc
index 035d337e5e51ebc9d9d5742c38a8df9eca8a87b1..239f0ece0ff40f7ed6bbdbda1176194a8103c966 100644 (file)
@@ -74,7 +74,6 @@ check_gl_error (char const * last)
 GLVideoView::GLVideoView (FilmViewer* viewer, wxWindow *parent)
        : VideoView (viewer)
        , _context (nullptr)
-       , _have_storage (false)
        , _vsync_enabled (false)
        , _playing (false)
        , _one_shot (false)
@@ -114,8 +113,6 @@ GLVideoView::~GLVideoView ()
                _thread.interrupt ();
                _thread.join ();
        } catch (...) {}
-
-       glDeleteTextures (1, &_video_texture);
 }
 
 void
@@ -464,7 +461,6 @@ GLVideoView::draw (Position<int>, dcp::Size)
        glViewport (0, 0, width, height);
        check_gl_error ("glViewport");
 
-       glBindTexture(GL_TEXTURE_2D, _video_texture);
        glBindVertexArray(_vao);
        check_gl_error ("glBindVertexArray");
        glUniform1i(_fragment_type, _optimise_for_j2k ? 1 : 2);
@@ -485,9 +481,9 @@ GLVideoView::draw (Position<int>, dcp::Size)
 void
 GLVideoView::set_image (shared_ptr<const PlayerVideo> pv)
 {
-       auto image = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true);
+       auto video = _optimise_for_j2k ? pv->raw_image() : pv->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, false, true);
 
-       DCPOMATIC_ASSERT (!image->aligned());
+       DCPOMATIC_ASSERT (!video->aligned());
 
        /** If _optimise_for_j2k is true we render a XYZ image, doing the colourspace
         *  conversion, scaling and video range conversion in the GL shader.
@@ -497,29 +493,15 @@ GLVideoView::set_image (shared_ptr<const PlayerVideo> pv)
        /* XXX: video range conversion */
        /* XXX: subs */
 
-       if (image->size() != _video_size) {
-               _have_storage = false;
-       }
-
-       _video_size = image->size ();
-       glPixelStorei (GL_UNPACK_ALIGNMENT, _optimise_for_j2k ? 2 : 1);
-       check_gl_error ("glPixelStorei");
-
-       auto const format = _optimise_for_j2k ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE;
-
-       if (_have_storage) {
-               glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, _video_size->width, _video_size->height, GL_RGB, format, image->data()[0]);
-               check_gl_error ("glTexSubImage2D");
-       } else {
-               glTexImage2D (GL_TEXTURE_2D, 0, _optimise_for_j2k ? GL_RGBA12 : GL_RGBA8, _video_size->width, _video_size->height, 0, GL_RGB, format, image->data()[0]);
-               check_gl_error ("glTexImage2D");
+       auto const changed = _video_texture->set (video);
 
+       if (changed) {
                auto const canvas_size = _canvas_size.load();
                int const canvas_width = canvas_size.GetWidth();
                int const canvas_height = canvas_size.GetHeight();
 
-               float const image_x = float(_video_size->width) / canvas_width;
-               float const image_y = float(_video_size->height) / canvas_height;
+               float const video_x = float(video->size().width) / canvas_width;
+               float const video_y = float(video->size().height) / canvas_height;
 
                auto x_pixels_to_gl = [canvas_width](int x) {
                        return (x * 2.0f / canvas_width) - 1.0f;
@@ -532,17 +514,17 @@ GLVideoView::set_image (shared_ptr<const PlayerVideo> pv)
                auto inter_position = player_video().first->inter_position();
                auto inter_size = player_video().first->inter_size();
 
-               float const border_x1 = x_pixels_to_gl (inter_position.x) + 1.0f - image_x;
-               float const border_y1 = y_pixels_to_gl (inter_position.y) + 1.0f - image_y;
-               float const border_x2 = x_pixels_to_gl (inter_position.x + inter_size.width) + 1.0f - image_x;
-               float const border_y2 = y_pixels_to_gl (inter_position.y + inter_size.height) + 1.0f - image_y;
+               float const border_x1 = x_pixels_to_gl (inter_position.x) + 1.0f - video_x;
+               float const border_y1 = y_pixels_to_gl (inter_position.y) + 1.0f - video_y;
+               float const border_x2 = x_pixels_to_gl (inter_position.x + inter_size.width) + 1.0f - video_x;
+               float const border_y2 = y_pixels_to_gl (inter_position.y + inter_size.height) + 1.0f - video_y;
 
                float vertices[] = {
                        // positions                  // texture coords
-                        image_x,   image_y,   0.0f,  1.0f, 0.0f,   // video texture top right    (index 0)
-                        image_x,  -image_y,   0.0f,  1.0f, 1.0f,   // video texture bottom right (index 1)
-                       -image_x,  -image_y,   0.0f,  0.0f, 1.0f,   // video texture bottom left  (index 2)
-                       -image_x,   image_y,   0.0f,  0.0f, 0.0f,   // video texture top left     (index 3)
+                        video_x,   video_y,   0.0f,  1.0f, 0.0f,   // video texture top right    (index 0)
+                        video_x,  -video_y,   0.0f,  1.0f, 1.0f,   // video texture bottom right (index 1)
+                       -video_x,  -video_y,   0.0f,  0.0f, 1.0f,   // video texture bottom left  (index 2)
+                       -video_x,   video_y,   0.0f,  0.0f, 0.0f,   // video texture top left     (index 3)
                         border_x1, border_y1, 0.0f,  0.0f, 0.0f,   // border bottom left         (index 4)
                         border_x1, border_y2, 0.0f,  0.0f, 0.0f,   // border top left            (index 5)
                         border_x2, border_y2, 0.0f,  0.0f, 0.0f,   // border top right           (index 6)
@@ -552,8 +534,6 @@ GLVideoView::set_image (shared_ptr<const PlayerVideo> pv)
                /* Set the vertex shader's input data (GL_ARRAY_BUFFER) */
                glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
                check_gl_error ("glBufferData");
-
-               _have_storage = true;
        }
 
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -668,10 +648,8 @@ try
        _vsync_enabled = true;
 #endif
 
-       glGenTextures (1, &_video_texture);
-       check_gl_error ("glGenTextures");
-       glBindTexture (GL_TEXTURE_2D, _video_texture);
-       check_gl_error ("glBindTexture");
+       _video_texture.reset(new Texture(_optimise_for_j2k ? 2 : 1));
+       _video_texture->bind();
 
        while (true) {
                boost::mutex::scoped_lock lm (_playing_mutex);
@@ -718,3 +696,49 @@ GLVideoView::request_one_shot ()
        _thread_work_condition.notify_all ();
 }
 
+
+Texture::Texture (GLint unpack_alignment)
+       : _unpack_alignment (unpack_alignment)
+{
+       glGenTextures (1, &_name);
+       check_gl_error ("glGenTextures");
+}
+
+
+Texture::~Texture ()
+{
+       glDeleteTextures (1, &_name);
+}
+
+
+void
+Texture::bind ()
+{
+       glBindTexture(GL_TEXTURE_2D, _name);
+       check_gl_error ("glBindTexture");
+}
+
+
+bool
+Texture::set (shared_ptr<const Image> image)
+{
+       auto const create = !_size || image->size() != _size;
+       _size = image->size();
+
+       glPixelStorei (GL_UNPACK_ALIGNMENT, _unpack_alignment);
+       check_gl_error ("glPixelStorei");
+
+       auto const format = image->pixel_format() == AV_PIX_FMT_RGB24 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
+       auto const internal_format = image->pixel_format() == AV_PIX_FMT_RGB24 ? GL_RGBA8 : GL_RGBA12;
+
+       if (create) {
+               glTexImage2D (GL_TEXTURE_2D, 0, internal_format, _size->width, _size->height, 0, GL_RGB, format, image->data()[0]);
+               check_gl_error ("glTexImage2D");
+       } else {
+               glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, _size->width, _size->height, GL_RGB, format, image->data()[0]);
+               check_gl_error ("glTexSubImage2D");
+       }
+
+       return create;
+}
+