Beispiel #1
0
static void
resolution(struct ctx *context, const struct wlc_size *mode, const struct wlc_size *resolution)
{
   assert(context && resolution);

   if (!wlc_size_equals(&context->resolution, resolution)) {
      for (GLuint i = 0; i < PROGRAM_LAST; ++i) {
         set_program(context, i);
         GL_CALL(glUniform2fv(context->program->uniforms[UNIFORM_RESOLUTION], 1, (GLfloat[]){ resolution->w, resolution->h }));
      }

      GL_CALL(glBindTexture(GL_TEXTURE_2D, context->textures[TEXTURE_FAKEFB]));
      GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, resolution->w, resolution->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
      clear_fakefb(context);
      context->resolution = *resolution;
   }

   if (!wlc_size_equals(&context->mode, mode)) {
      GL_CALL(glViewport(0, 0, mode->w, mode->h));
      context->mode = *mode;
   }
}
Beispiel #2
0
static void
texture_paint(struct ctx *context, GLuint *textures, GLuint nmemb, const struct wlc_geometry *geometry, struct paint *settings)
{
   const GLfloat vertices[8] = {
      geometry->origin.x + geometry->size.w, geometry->origin.y,
      geometry->origin.x, geometry->origin.y,
      geometry->origin.x + geometry->size.w, geometry->origin.y + geometry->size.h,
      geometry->origin.x, geometry->origin.y + geometry->size.h,
   };

   const GLfloat coords[8] = {
      1, 0,
      0, 0,
      1, 1,
      0, 1
   };

   set_program(context, settings->program);

   if (settings->dim > 0.0f) {
      GL_CALL(glUniform1fv(context->program->uniforms[UNIFORM_DIM], 1, &settings->dim));
   }

   for (GLuint i = 0; i < nmemb; ++i) {
      if (!textures[i])
         break;

      GL_CALL(glActiveTexture(GL_TEXTURE0 + i));
      GL_CALL(glBindTexture(GL_TEXTURE_2D, textures[i]));

      if (settings->filter || !wlc_size_equals(&context->resolution, &context->mode)) {
         GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
         GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
      } else {
         GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
         GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
      }
   }

   GL_CALL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices));
   GL_CALL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, coords));
   GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
Beispiel #3
0
static void
surface_paint_internal(struct ctx *context, struct wlc_surface *surface, const struct wlc_geometry *geometry, struct paint *settings)
{
   assert(context && surface && geometry && settings);

   const struct wlc_geometry *g = geometry;

   if (!wlc_size_equals(&surface->size, &geometry->size)) {
      if (wlc_geometry_equals(&settings->visible, geometry)) {
         settings->filter = true;
      } else {
         // black borders are requested
         struct paint settings2 = *settings;
         settings2.program = (settings2.program == PROGRAM_RGBA || settings2.program == PROGRAM_RGB ? settings2.program : PROGRAM_RGB);
         texture_paint(context, &context->textures[TEXTURE_BLACK], 1, geometry, &settings2);
         g = &settings->visible;
      }
   }

   texture_paint(context, surface->textures, 3, g, settings);
}
Beispiel #4
0
Datei: view.c Projekt: snells/wlc
void
wlc_view_commit_state(struct wlc_view *view, struct wlc_view_state *pending, struct wlc_view_state *out)
{
   struct wlc_surface *surface;
   if (!(surface = convert_from_wlc_resource(view->surface, "surface")))
      return;

   // FIXME: handle ping
#if 0
      struct wl_resource *r;
      if (view->shell_surface && (r = wl_resource_from_wlc_resource(view->shell_surface, "shell-surface")))
         wl_shell_surface_send_ping(r, wl_display_next_serial(wlc_display()));

      wlc_dlog(WLC_DBG_COMMIT, "=> ping view %zu", convert_to_wlc_handle(view));
      return;
#endif

   if (!view->state.created) {
      // Initial size of the view
      view->pending.geometry.size = surface->size;
      view->state.created = true;

      if (WLC_INTERFACE_EMIT_EXCEPT(view.created, false, convert_to_wlc_handle(view))) {
         wlc_view_close_ptr(view);
         return;
      }
   }

   if (!memcmp(pending, out, sizeof(struct wlc_view_state)))
      return;

   if (pending->state != out->state) {
      const struct {
         uint32_t bit;
         uint32_t state;
      } map[] = {
         { WLC_BIT_MAXIMIZED, XDG_SURFACE_STATE_MAXIMIZED },
         { WLC_BIT_FULLSCREEN, XDG_SURFACE_STATE_FULLSCREEN },
         { WLC_BIT_RESIZING, XDG_SURFACE_STATE_RESIZING },
         { WLC_BIT_ACTIVATED, XDG_SURFACE_STATE_ACTIVATED },
         { 0, 0 },
      };

      chck_iter_pool_flush(&view->wl_state);

      for (uint32_t i = 0; map[i].state != 0; ++i) {
         if (pending->state & map[i].bit)
            chck_iter_pool_push_back(&view->wl_state, &map[i].state);
      }
   }

   const bool size_changed = (!wlc_size_equals(&pending->geometry.size, &out->geometry.size) || !wlc_size_equals(&pending->geometry.size, &surface->size));
   wlc_dlog(WLC_DBG_COMMIT, "=> pending commit %zu (%d) pending: %ux%u commited: %ux%u surface: %ux%u", convert_to_wlc_handle(view), size_changed, pending->geometry.size.w, pending->geometry.size.h, out->geometry.size.w, out->geometry.size.h, surface->size.w, surface->size.h);

   if (pending->state != out->state || size_changed) {
      struct wl_resource *r;
      if (view->xdg_surface && (r = wl_resource_from_wlc_resource(view->xdg_surface, "xdg-surface"))) {
         const uint32_t serial = wl_display_next_serial(wlc_display());
         struct wl_array states = { .size = view->wl_state.items.used, .alloc = view->wl_state.items.allocated, .data = view->wl_state.items.buffer };
         xdg_surface_send_configure(r, pending->geometry.size.w, pending->geometry.size.h, &states, serial);
      } else if (view->shell_surface && (r = wl_resource_from_wlc_resource(view->shell_surface, "shell-surface"))) {
         wl_shell_surface_send_configure(r, pending->edges, pending->geometry.size.w, pending->geometry.size.h);
      }
   }

   if (view->x11.id) {
      if (!wlc_origin_equals(&pending->geometry.origin, &out->geometry.origin))
         wlc_x11_window_position(&view->x11, pending->geometry.origin.x, pending->geometry.origin.y);

      if (size_changed)
         wlc_x11_window_resize(&view->x11, pending->geometry.size.w, pending->geometry.size.h);
   }

   memcpy(out, pending, sizeof(struct wlc_view_state));
   wlc_dlog(WLC_DBG_COMMIT, "=> commit %zu", convert_to_wlc_handle(view));
}
Beispiel #5
0
void
wlc_view_commit_state(struct wlc_view *view, struct wlc_view_state *pending, struct wlc_view_state *out)
{
   assert(view && pending && out);

   struct wlc_surface *surface;
   if (!(surface = convert_from_wlc_resource(view->surface, "surface")))
      return;

   // FIXME: handle ping
#if 0
      struct wl_resource *r;
      if (view->shell_surface && (r = wl_resource_from_wlc_resource(view->shell_surface, "shell-surface")))
         wl_shell_surface_send_ping(r, wl_display_next_serial(wlc_display()));

      wlc_dlog(WLC_DBG_COMMIT, "=> ping view %" PRIuWLC, convert_to_wlc_handle(view));
      return;
#endif

   if (!view->state.created) {
      // Initial size of the view
      view->pending.geometry.size = surface->size;
      view->state.created = true;

      if (WLC_INTERFACE_EMIT_EXCEPT(view.created, false, convert_to_wlc_handle(view))) {
         wlc_view_close_ptr(view);
         return;
      }
   }

   if (!memcmp(pending, out, sizeof(struct wlc_view_state)))
      return;

   if (pending->state != out->state) {
      const struct {
         enum wlc_view_state_bit bit;
         uint32_t state;
      } map[] = {
         { WLC_BIT_MAXIMIZED, XDG_SURFACE_STATE_MAXIMIZED },
         { WLC_BIT_FULLSCREEN, XDG_SURFACE_STATE_FULLSCREEN },
         { WLC_BIT_RESIZING, XDG_SURFACE_STATE_RESIZING },
         { WLC_BIT_ACTIVATED, XDG_SURFACE_STATE_ACTIVATED },
      };

      chck_iter_pool_flush(&view->wl_state);

      for (uint32_t i = 0; i < LENGTH(map); ++i) {
         if (pending->state & map[i].bit)
            chck_iter_pool_push_back(&view->wl_state, &map[i].state);
      }
   }

   const bool size_changed = (!wlc_size_equals(&pending->geometry.size, &out->geometry.size) || !wlc_size_equals(&pending->geometry.size, &surface->size));
   wlc_dlog(WLC_DBG_COMMIT, "=> pending view commit %" PRIuWLC " (%d) pending: %ux%u commited: %ux%u surface: %ux%u", convert_to_wlc_handle(view), size_changed, pending->geometry.size.w, pending->geometry.size.h, out->geometry.size.w, out->geometry.size.h, surface->size.w, surface->size.h);

   if (pending->state != out->state || size_changed)
      configure_view(view, pending->edges, &pending->geometry);

   *out = *pending;
   wlc_dlog(WLC_DBG_COMMIT, "=> commit view %" PRIuWLC, convert_to_wlc_handle(view));
}
Beispiel #6
0
void
wlc_view_ack_surface_attach(struct wlc_view *view, struct wlc_surface *surface)
{
   assert(view && surface);

   if (is_x11_view(view)) {
      surface->pending.opaque.extents = (pixman_box32_t){ 0, 0, surface->size.w, surface->size.h };
      view->surface_pending.visible = (struct wlc_geometry){ wlc_point_zero, surface->size };
   }

   const bool resizing = (view->pending.state & WLC_BIT_RESIZING || view->commit.state & WLC_BIT_RESIZING);
   if (!resizing && !wlc_geometry_equals(&view->surface_pending.visible, &view->surface_commit.visible)) {
      struct wlc_geometry g = (struct wlc_geometry){ view->pending.geometry.origin, view->surface_pending.visible.size };
      wlc_view_request_geometry(view, &g);
   }

   view->surface_commit = view->surface_pending;
}

void
wlc_view_get_bounds(struct wlc_view *view, struct wlc_geometry *out_bounds, struct wlc_geometry *out_visible)
{
   assert(view && out_bounds && out_bounds != out_visible);
   memcpy(out_bounds, &view->commit.geometry, sizeof(struct wlc_geometry));

   struct wlc_surface *surface;
   if (!(surface = convert_from_wlc_resource(view->surface, "surface")))
      return;

   if (view->xdg_surface && !wlc_size_equals(&view->surface_commit.visible.size, &wlc_size_zero)) {
      // xdg-surface client that draws drop shadows or other stuff.
      struct wlc_geometry v = view->surface_commit.visible;
      v.origin.x = chck_clamp32(v.origin.x, 0, surface->size.w);
      v.origin.y = chck_clamp32(v.origin.y, 0, surface->size.h);
      v.size.w = chck_clampu32(surface->size.w - v.size.w, 0, surface->size.w);
      v.size.h = chck_clampu32(surface->size.h - v.size.h, 0, surface->size.h);

      assert(surface->size.w > 0 && surface->size.h > 0);
      const float wa = (float)out_bounds->size.w / surface->size.w, ha = (float)out_bounds->size.h / surface->size.h;

      out_bounds->origin.x -= v.origin.x * wa;
      out_bounds->origin.y -= v.origin.y * ha;
      out_bounds->size.w += v.size.w * wa;
      out_bounds->size.h += v.size.h * ha;
   }

   // Make sure bounds is never 0x0 w/h
   wlc_size_max(&out_bounds->size, &(struct wlc_size){ 1, 1 }, &out_bounds->size);

   if (!out_visible)
      return;

   // Actual visible area of the view
   // The idea is to draw black borders to the bounds area, while centering the visible area.
   if ((is_x11_view(view) || view->shell_surface) && !wlc_size_equals(&surface->size, &out_bounds->size)) {
      out_visible->size = surface->size;

      // Scale visible area retaining aspect
      assert(surface->size.w > 0 && surface->size.h > 0);
      const float ba = (float)out_bounds->size.w / (float)out_bounds->size.h;
      const float sa = (float)surface->size.w / (float)surface->size.h;
      if (ba < sa) {
         out_visible->size.w *= (float)out_bounds->size.w / surface->size.w;
         out_visible->size.h *= (float)out_bounds->size.w / surface->size.w;
      } else {
         out_visible->size.w *= (float)out_bounds->size.h / surface->size.h;
         out_visible->size.h *= (float)out_bounds->size.h / surface->size.h;
      }

      // Center visible area
      out_visible->origin.x = out_bounds->origin.x + out_bounds->size.w * 0.5 - out_visible->size.w * 0.5;
      out_visible->origin.y = out_bounds->origin.y + out_bounds->size.h * 0.5 - out_visible->size.h * 0.5;

      // Make sure visible is never 0x0 w/h
      out_visible->size.w = chck_maxu32(out_visible->size.w, 1);
      out_visible->size.h = chck_maxu32(out_visible->size.h, 1);
   } else {
      // For non wl_shell or x11 surfaces, just memcpy
      memcpy(out_visible, out_bounds, sizeof(struct wlc_geometry));
   }
}