blob: b776a3badbce9f342971f9c130d926389ecd78ab [file] [log] [blame]
krit@webkit.org84792472009-08-08 19:11:35 +00001/*
2 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
krit@webkit.org0995b2d2011-07-09 06:05:14 +00003 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
said@apple.com8eabfa22022-02-10 05:18:02 +00004 * Copyright (C) 2016-2022 Apple Inc. All rights reserved.
krit@webkit.org84792472009-08-08 19:11:35 +00005 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
mjs@apple.com92047332014-03-15 04:08:27 +000015 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
krit@webkit.org84792472009-08-08 19:11:35 +000016 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
mjs@apple.com92047332014-03-15 04:08:27 +000018 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
krit@webkit.org84792472009-08-08 19:11:35 +000019 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "ImageBuffer.h"
30
commit-queue@webkit.orgf3676f52022-06-07 13:43:49 +000031#include "BitmapImage.h"
simon.fraser@apple.com6ce84df2014-04-18 18:35:20 +000032#include "GraphicsContext.h"
commit-queue@webkit.org1107a9b2020-02-25 18:49:00 +000033#include "HostWindow.h"
commit-queue@webkit.orgaa9a4202020-02-19 01:12:47 +000034#include "PlatformImageBuffer.h"
krit@webkit.org84792472009-08-08 19:11:35 +000035
36namespace WebCore {
37
commit-queue@webkit.orgef9df182015-05-07 22:46:43 +000038static const float MaxClampedLength = 4096;
39static const float MaxClampedArea = MaxClampedLength * MaxClampedLength;
40
simon.fraser@apple.com4d626762022-04-06 15:22:41 +000041RefPtr<ImageBuffer> ImageBuffer::create(const FloatSize& size, RenderingPurpose purpose, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat, OptionSet<ImageBufferOptions> options, const CreationContext& creationContext)
wenson_hsieh@apple.com69379742020-02-29 03:00:22 +000042{
said@apple.com604a4f62020-11-03 19:38:41 +000043 RefPtr<ImageBuffer> imageBuffer;
said@apple.com21355932021-02-24 17:58:32 +000044
simon.fraser@apple.com4d626762022-04-06 15:22:41 +000045 // Give UseDisplayList a higher precedence since it is a debug option.
46 if (options.contains(ImageBufferOptions::UseDisplayList)) {
47 if (options.contains(ImageBufferOptions::Accelerated))
simon.fraser@apple.com71d94952022-04-07 20:13:53 +000048 imageBuffer = DisplayListAcceleratedImageBuffer::create(size, resolutionScale, colorSpace, pixelFormat, purpose, creationContext);
said@apple.come4d57372020-10-28 01:36:51 +000049
50 if (!imageBuffer)
simon.fraser@apple.com71d94952022-04-07 20:13:53 +000051 imageBuffer = DisplayListUnacceleratedImageBuffer::create(size, resolutionScale, colorSpace, pixelFormat, purpose, creationContext);
wenson_hsieh@apple.com69379742020-02-29 03:00:22 +000052 }
said@apple.com21355932021-02-24 17:58:32 +000053
simon.fraser@apple.com4d626762022-04-06 15:22:41 +000054 if (creationContext.hostWindow && !imageBuffer) {
55 auto renderingMode = options.contains(ImageBufferOptions::Accelerated) ? RenderingMode::Accelerated : RenderingMode::Unaccelerated;
simon.fraser@apple.comce6dd1f2022-04-03 05:24:35 +000056 imageBuffer = creationContext.hostWindow->createImageBuffer(size, renderingMode, purpose, resolutionScale, colorSpace, pixelFormat);
simon.fraser@apple.com4d626762022-04-06 15:22:41 +000057 }
wenson_hsieh@apple.com69379742020-02-29 03:00:22 +000058
simon.fraser@apple.com4d626762022-04-06 15:22:41 +000059 if (imageBuffer)
60 return imageBuffer;
said@apple.come4d57372020-10-28 01:36:51 +000061
simon.fraser@apple.com4d626762022-04-06 15:22:41 +000062 if (options.contains(ImageBufferOptions::Accelerated))
simon.fraser@apple.com71d94952022-04-07 20:13:53 +000063 imageBuffer = AcceleratedImageBuffer::create(size, resolutionScale, colorSpace, pixelFormat, purpose, creationContext);
said@apple.come4d57372020-10-28 01:36:51 +000064
65 if (!imageBuffer)
simon.fraser@apple.com71d94952022-04-07 20:13:53 +000066 imageBuffer = UnacceleratedImageBuffer::create(size, resolutionScale, colorSpace, pixelFormat, purpose, creationContext);
commit-queue@webkit.orgaa9a4202020-02-19 01:12:47 +000067
68 return imageBuffer;
bfulgham@apple.com60d08fe2016-10-14 22:42:14 +000069}
70
said@apple.com8eabfa22022-02-10 05:18:02 +000071RefPtr<ImageBuffer> ImageBuffer::clone() const
commit-queue@webkit.orgaa9a4202020-02-19 01:12:47 +000072{
said@apple.coma22fc222022-03-01 23:16:43 +000073 auto clone = context().createAlignedImageBuffer(logicalSize(), colorSpace());
said@apple.com8eabfa22022-02-10 05:18:02 +000074 if (!clone)
commit-queue@webkit.orgaa9a4202020-02-19 01:12:47 +000075 return nullptr;
76
said@apple.com8eabfa22022-02-10 05:18:02 +000077 clone->context().drawImageBuffer(const_cast<ImageBuffer&>(*this), FloatPoint());
78 return clone;
commit-queue@webkit.orgaa9a4202020-02-19 01:12:47 +000079}
bfulgham@apple.com60d08fe2016-10-14 22:42:14 +000080
said@apple.comb5a71a92015-05-07 23:32:45 +000081bool ImageBuffer::sizeNeedsClamping(const FloatSize& size)
commit-queue@webkit.orgef9df182015-05-07 22:46:43 +000082{
said@apple.comb5a71a92015-05-07 23:32:45 +000083 if (size.isEmpty())
commit-queue@webkit.orgef9df182015-05-07 22:46:43 +000084 return false;
85
said@apple.comb5a71a92015-05-07 23:32:45 +000086 return floorf(size.height()) * floorf(size.width()) > MaxClampedArea;
commit-queue@webkit.orgef9df182015-05-07 22:46:43 +000087}
88
said@apple.comb5a71a92015-05-07 23:32:45 +000089bool ImageBuffer::sizeNeedsClamping(const FloatSize& size, FloatSize& scale)
commit-queue@webkit.orgef9df182015-05-07 22:46:43 +000090{
91 FloatSize scaledSize(size);
92 scaledSize.scale(scale.width(), scale.height());
93
said@apple.comb5a71a92015-05-07 23:32:45 +000094 if (!sizeNeedsClamping(scaledSize))
95 return false;
commit-queue@webkit.orgef9df182015-05-07 22:46:43 +000096
97 // The area of scaled size is bigger than the upper limit, adjust the scale to fit.
98 scale.scale(sqrtf(MaxClampedArea / (scaledSize.width() * scaledSize.height())));
said@apple.comb5a71a92015-05-07 23:32:45 +000099 ASSERT(!sizeNeedsClamping(size, scale));
100 return true;
commit-queue@webkit.orgef9df182015-05-07 22:46:43 +0000101}
102
103FloatSize ImageBuffer::clampedSize(const FloatSize& size)
104{
105 return size.shrunkTo(FloatSize(MaxClampedLength, MaxClampedLength));
106}
107
108FloatSize ImageBuffer::clampedSize(const FloatSize& size, FloatSize& scale)
109{
110 if (size.isEmpty())
111 return size;
112
113 FloatSize clampedSize = ImageBuffer::clampedSize(size);
simon.fraser@apple.com726bd782017-09-20 06:13:54 +0000114 scale = clampedSize / size;
said@apple.comb5a71a92015-05-07 23:32:45 +0000115 ASSERT(!sizeNeedsClamping(clampedSize));
116 ASSERT(!sizeNeedsClamping(size, scale));
commit-queue@webkit.orgef9df182015-05-07 22:46:43 +0000117 return clampedSize;
118}
119
120FloatRect ImageBuffer::clampedRect(const FloatRect& rect)
121{
122 return FloatRect(rect.location(), clampedSize(rect.size()));
123}
124
commit-queue@webkit.orgf3676f52022-06-07 13:43:49 +0000125RefPtr<NativeImage> ImageBuffer::sinkIntoNativeImage(RefPtr<ImageBuffer> source)
commit-queue@webkit.org0f9edcc2016-06-03 00:39:58 +0000126{
commit-queue@webkit.orgf3676f52022-06-07 13:43:49 +0000127 if (!source)
128 return nullptr;
129 return source->sinkIntoNativeImage();
commit-queue@webkit.org0f9edcc2016-06-03 00:39:58 +0000130}
131
commit-queue@webkit.orgf3676f52022-06-07 13:43:49 +0000132RefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, PreserveResolution preserveResolution) const
junov@google.comf50296b2012-12-05 21:40:26 +0000133{
commit-queue@webkit.orgf3676f52022-06-07 13:43:49 +0000134 RefPtr<NativeImage> image;
135 if (resolutionScale() == 1 || preserveResolution == PreserveResolution::Yes)
136 image = copyNativeImage(copyBehavior);
137 else {
138 auto copyBuffer = context().createImageBuffer(logicalSize(), 1.f, colorSpace());
139 if (!copyBuffer)
140 return nullptr;
141 copyBuffer->context().drawImageBuffer(const_cast<ImageBuffer&>(*this), FloatPoint { }, CompositeOperator::Copy);
142 image = ImageBuffer::sinkIntoNativeImage(WTFMove(copyBuffer));
143 }
144 if (!image)
145 return nullptr;
146 return BitmapImage::create(image.releaseNonNull());
147}
148
149RefPtr<Image> ImageBuffer::sinkIntoImage(RefPtr<ImageBuffer> source, PreserveResolution preserveResolution)
150{
151 if (!source)
152 return nullptr;
153 RefPtr<NativeImage> image;
154 if (source->resolutionScale() == 1 || preserveResolution == PreserveResolution::Yes)
155 image = sinkIntoNativeImage(WTFMove(source));
156 else {
157 auto copySize = source->logicalSize();
158 auto copyBuffer = source->context().createImageBuffer(copySize, 1.f, source->colorSpace());
159 if (!copyBuffer)
160 return nullptr;
161 drawConsuming(WTFMove(source), copyBuffer->context(), FloatRect { { }, copySize }, FloatRect { 0, 0, -1, -1 }, CompositeOperator::Copy);
162 image = ImageBuffer::sinkIntoNativeImage(WTFMove(copyBuffer));
163 }
164 if (!image)
165 return nullptr;
166 return BitmapImage::create(image.releaseNonNull());
junov@google.comf50296b2012-12-05 21:40:26 +0000167}
commit-queue@webkit.org8a3af352012-06-22 20:45:52 +0000168
said@apple.com604a4f62020-11-03 19:38:41 +0000169void ImageBuffer::drawConsuming(RefPtr<ImageBuffer> imageBuffer, GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
commit-queue@webkit.org0f9edcc2016-06-03 00:39:58 +0000170{
commit-queue@webkit.orgaa9a4202020-02-19 01:12:47 +0000171 imageBuffer->drawConsuming(context, destRect, srcRect, options);
commit-queue@webkit.org0f9edcc2016-06-03 00:39:58 +0000172}
173
commit-queue@webkit.orgaa9a4202020-02-19 01:12:47 +0000174} // namespace WebCore