| // Copyright 2019 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "components/exo/wayland/zcr_alpha_compositing.h" | 
 |  | 
 | #include <alpha-compositing-unstable-v1-server-protocol.h> | 
 |  | 
 | #include "base/memory/raw_ptr.h" | 
 | #include "components/exo/surface.h" | 
 | #include "components/exo/surface_observer.h" | 
 | #include "components/exo/wayland/server_util.h" | 
 |  | 
 | namespace exo { | 
 | namespace wayland { | 
 | namespace { | 
 |  | 
 | // A property key containing a boolean set to true if a blending object is | 
 | // associated with surface object. | 
 | DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSurfaceHasBlendingKey, false) | 
 |  | 
 | //////////////////////////////////////////////////////////////////////////////// | 
 | // blending_interface: | 
 |  | 
 | // Implements the blending interface to a Surface. The "blend mode" and | 
 | // "alpha"-state is set to SrcOver and 1 upon destruction. A window property | 
 | // will be set during the lifetime of this class to prevent multiple instances | 
 | // from being created for the same Surface. | 
 | class Blending : public SurfaceObserver { | 
 |  public: | 
 |   explicit Blending(Surface* surface) : surface_(surface) { | 
 |     surface_->AddSurfaceObserver(this); | 
 |     surface_->SetProperty(kSurfaceHasBlendingKey, true); | 
 |   } | 
 |  | 
 |   Blending(const Blending&) = delete; | 
 |   Blending& operator=(const Blending&) = delete; | 
 |  | 
 |   ~Blending() override { | 
 |     if (surface_) { | 
 |       surface_->RemoveSurfaceObserver(this); | 
 |       surface_->SetBlendMode(SkBlendMode::kSrcOver); | 
 |       surface_->SetAlpha(1.0f); | 
 |       surface_->SetProperty(kSurfaceHasBlendingKey, false); | 
 |     } | 
 |   } | 
 |  | 
 |   void SetBlendMode(SkBlendMode blend_mode) { | 
 |     if (surface_) | 
 |       surface_->SetBlendMode(blend_mode); | 
 |   } | 
 |  | 
 |   void SetAlpha(float value) { | 
 |     if (surface_) | 
 |       surface_->SetAlpha(value); | 
 |   } | 
 |  | 
 |   // Overridden from SurfaceObserver: | 
 |   void OnSurfaceDestroying(Surface* surface) override { | 
 |     surface->RemoveSurfaceObserver(this); | 
 |     surface_ = nullptr; | 
 |   } | 
 |  | 
 |  private: | 
 |   raw_ptr<Surface> surface_; | 
 | }; | 
 |  | 
 | void blending_destroy(wl_client* client, wl_resource* resource) { | 
 |   wl_resource_destroy(resource); | 
 | } | 
 |  | 
 | void blending_set_blending(wl_client* client, | 
 |                            wl_resource* resource, | 
 |                            uint32_t equation) { | 
 |   switch (equation) { | 
 |     case ZCR_BLENDING_V1_BLENDING_EQUATION_NONE: | 
 |       GetUserDataAs<Blending>(resource)->SetBlendMode(SkBlendMode::kSrc); | 
 |       break; | 
 |     case ZCR_BLENDING_V1_BLENDING_EQUATION_PREMULT: | 
 |       GetUserDataAs<Blending>(resource)->SetBlendMode(SkBlendMode::kSrcOver); | 
 |       break; | 
 |     case ZCR_BLENDING_V1_BLENDING_EQUATION_COVERAGE: | 
 |       NOTIMPLEMENTED(); | 
 |       break; | 
 |     default: | 
 |       DLOG(WARNING) << "Unsupported blending equation: " << equation; | 
 |       break; | 
 |   } | 
 | } | 
 |  | 
 | void blending_set_alpha(wl_client* client, | 
 |                         wl_resource* resource, | 
 |                         wl_fixed_t alpha) { | 
 |   GetUserDataAs<Blending>(resource)->SetAlpha(wl_fixed_to_double(alpha)); | 
 | } | 
 |  | 
 | const struct zcr_blending_v1_interface blending_implementation = { | 
 |     blending_destroy, blending_set_blending, blending_set_alpha}; | 
 |  | 
 | //////////////////////////////////////////////////////////////////////////////// | 
 | // alpha_compositing_interface: | 
 |  | 
 | void alpha_compositing_destroy(wl_client* client, wl_resource* resource) { | 
 |   wl_resource_destroy(resource); | 
 | } | 
 |  | 
 | void alpha_compositing_get_blending(wl_client* client, | 
 |                                     wl_resource* resource, | 
 |                                     uint32_t id, | 
 |                                     wl_resource* surface_resource) { | 
 |   Surface* surface = GetUserDataAs<Surface>(surface_resource); | 
 |   if (surface->GetProperty(kSurfaceHasBlendingKey)) { | 
 |     wl_resource_post_error(resource, | 
 |                            ZCR_ALPHA_COMPOSITING_V1_ERROR_BLENDING_EXISTS, | 
 |                            "a blending object for that surface already exists"); | 
 |     return; | 
 |   } | 
 |  | 
 |   wl_resource* blending_resource = | 
 |       wl_resource_create(client, &zcr_blending_v1_interface, 1, id); | 
 |  | 
 |   SetImplementation(blending_resource, &blending_implementation, | 
 |                     std::make_unique<Blending>(surface)); | 
 | } | 
 |  | 
 | const struct zcr_alpha_compositing_v1_interface | 
 |     alpha_compositing_implementation = {alpha_compositing_destroy, | 
 |                                         alpha_compositing_get_blending}; | 
 |  | 
 | }  // namespace | 
 |  | 
 | void bind_alpha_compositing(wl_client* client, | 
 |                             void* data, | 
 |                             uint32_t version, | 
 |                             uint32_t id) { | 
 |   wl_resource* resource = | 
 |       wl_resource_create(client, &zcr_alpha_compositing_v1_interface, 1, id); | 
 |  | 
 |   wl_resource_set_implementation(resource, &alpha_compositing_implementation, | 
 |                                  data, nullptr); | 
 | } | 
 |  | 
 | }  // namespace wayland | 
 | }  // namespace exo |