summaryrefslogtreecommitdiff
path: root/gfx/layers/basic/X11BasicCompositor.cpp
blob: 6f21d15d27bd889fd3182407dd0791b4edb798dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "X11BasicCompositor.h"
#include "gfxPlatform.h"
#include "gfx2DGlue.h"
#include "gfxXlibSurface.h"
#include "gfxImageSurface.h"
#include "mozilla/X11Util.h"

namespace mozilla {
using namespace mozilla::gfx;

namespace layers {

bool
X11DataTextureSourceBasic::Update(gfx::DataSourceSurface* aSurface,
                                  nsIntRegion* aDestRegion,
                                  gfx::IntPoint* aSrcOffset)
{
  // Reallocate our internal X11 surface if we don't have a DrawTarget yet,
  // or if we changed surface size or format since last update.
  if (!mBufferDrawTarget ||
      (aSurface->GetSize() != mBufferDrawTarget->GetSize()) ||
      (aSurface->GetFormat() != mBufferDrawTarget->GetFormat())) {

    RefPtr<gfxASurface> surf;
    gfxImageFormat imageFormat = SurfaceFormatToImageFormat(aSurface->GetFormat());
    Display *display = DefaultXDisplay();
    Screen *screen = DefaultScreenOfDisplay(display);
    XRenderPictFormat *xrenderFormat =
      gfxXlibSurface::FindRenderFormat(display, imageFormat);

    if (xrenderFormat) {
      surf = gfxXlibSurface::Create(screen, xrenderFormat,
                                    aSurface->GetSize());
    }

    if (!surf) {
      NS_WARNING("Couldn't create native surface, fallback to image surface");
      surf = new gfxImageSurface(aSurface->GetSize(), imageFormat);
    }

    mBufferDrawTarget = gfxPlatform::GetPlatform()->
      CreateDrawTargetForSurface(surf, aSurface->GetSize());
  }

  // Image contents have changed, upload to our DrawTarget
  // If aDestRegion is null, means we're updating the whole surface
  // Note : Incremental update with a source offset is only used on Mac.
  NS_ASSERTION(!aSrcOffset, "SrcOffset should not be used with linux OMTC basic");

  if (aDestRegion) {
    for (auto iter = aDestRegion->RectIter(); !iter.Done(); iter.Next()) {
      const IntRect& rect = iter.Get();
      IntRect srcRect(rect.x, rect.y, rect.width, rect.height);
      IntPoint dstPoint(rect.x, rect.y);

      // We're uploading regions to our buffer, so let's just copy contents over
      mBufferDrawTarget->CopySurface(aSurface, srcRect, dstPoint);
    }
  } else {
    // We're uploading the whole buffer, so let's just copy the full surface
    IntSize size = aSurface->GetSize();
    mBufferDrawTarget->CopySurface(aSurface, IntRect(0, 0, size.width, size.height),
                                   IntPoint(0, 0));
  }

  return true;
}

TextureSourceBasic*
X11DataTextureSourceBasic::AsSourceBasic()
{
  return this;
}

IntSize
X11DataTextureSourceBasic::GetSize() const
{
  if (!mBufferDrawTarget) {
    NS_WARNING("Trying to query the size of an uninitialized TextureSource");
    return IntSize(0, 0);
  } else {
    return mBufferDrawTarget->GetSize();
  }
}

gfx::SurfaceFormat
X11DataTextureSourceBasic::GetFormat() const
{
  if (!mBufferDrawTarget) {
    NS_WARNING("Trying to query the format of an uninitialized TextureSource");
    return gfx::SurfaceFormat::UNKNOWN;
  } else {
    return mBufferDrawTarget->GetFormat();
  }
}

SourceSurface*
X11DataTextureSourceBasic::GetSurface(DrawTarget* aTarget)
{
  RefPtr<gfx::SourceSurface> surface;
  if (mBufferDrawTarget) {
    surface = mBufferDrawTarget->Snapshot();
    return surface.get();
  } else {
    return nullptr;
  }
}

void
X11DataTextureSourceBasic::DeallocateDeviceData()
{
  mBufferDrawTarget = nullptr;
}

already_AddRefed<DataTextureSource>
X11BasicCompositor::CreateDataTextureSource(TextureFlags aFlags)
{
  RefPtr<DataTextureSource> result =
    new X11DataTextureSourceBasic();
  return result.forget();
}

void
X11BasicCompositor::EndFrame()
{
  BasicCompositor::EndFrame();
  XFlush(DefaultXDisplay());
}

} // namespace layers
} // namespace mozilla